文章内容为LeetCode刷题笔记,如发现错误请多多指教
29、二叉树深度:二叉树深度的统计方法
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
关于深度的计算,可以有两种办法:1、递归 2、层次遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
//层次遍历
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==nullptr){
return 0;
}
int depth=0;
//TreeNode *t=root;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size=q.size();
depth++;
//层序遍历获得深度的精髓在于每遍历一层depth++一次
for(int i=0;i<size;i++){
TreeNode *t=q.front();
q.pop();
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
}
return depth;
}
};
//递归一
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==nullptr){
return 0;
}
return 1+max(maxDepth(root->left),maxDepth(root->right));
}
};
//递归二
class Solution {
public:
void maxDepthHelper(TreeNode* root,int curr,int &max){
if(root==nullptr){
if(max<curr){
max=curr;
}
return;
}
maxDepthHelper(root->left,curr+1,max);
maxDepthHelper(root->right,curr+1,max);
}
int maxDepth(TreeNode* root) {
if(root==nullptr){
return 0;
}
int curr=0;
int max=0;
maxDepthHelper(root,curr,max);
return max;
}
};
30、只出现一次的数字|||:异或运算,位运算
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
采用位运算的详细思路
class Solution {
public:
vector<int> singleNumber(vector<int>& nums)
{
int sign = 0;
//取得数组中两个唯一数的按位异或结果
for (int i = 0; i < nums.size(); i++)
{
sign ^= nums[i];
}
//获取区分两个唯一数的比特位所代表的值
//也可以写成:sign &= (~sign) + 1
sign &= -sign;
int n1 = 0, n2 = 0;
//通过标识,区分两个数组
for (int i = 0; i < nums.size(); i++)
{
if ((nums[i] & sign) == sign)
n1 ^= nums[i];
else
n2 ^= nums[i]; ;
}
return { n1,n2 };
}
};
31、和为s的连续正整数序列:场景转化模型,滑动窗口
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
这个题可以采用滑动窗口的思想来解决,关键就在于确定合法的连续区间,这个区间如何确立呢,就需要不断调整区间的大小并不断后移,所以采用两个数来实现,具体代码:
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
//建立返回数组
vector<vector<int>> result;
int low=1;
int high=2;
while(low<high){
//计算这个连续区间的和
int totle=(low+high)*(high-low+1)/2;
//如果和与目标值相同,那么将这个序列放入返回数组中
if(totle==target){
vector<int> nums;
for(int i=low;i<=high;i++){
nums.push_back(i);
}
result.push_back(nums);
high++;//这里low++和high++都可,因为后面会调整
}
//如果和比目标值小了,那就扩大区间大小,后面的值后移
else if(totle<target){
high++;
}
//如果和比目标值打了。缩小区间,前面的值后移
else{
low++;
}
}
return result;
}
};
32、左循环字符串:字符串逆置,循环次数去重
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"
这个题可以用好几种思路,一种是把整体在后面加一遍,比如12345变成1234512345,旋转几次就在中间取就可以了;另一种是一个一个后移,一共移动k个就可;最后一个思路是先局部逆置,再整体逆置。
//思路一:字符串加一遍在中间取值
class Solution {
public:
string reverseLeftWords(string s, int n) {
string t=s+s;
string result;
int length=s.length();
if(n<=0){
return s;
}
int m=n%length;
for(int i=m;i<length+m;i++){
result+=t[i];
}
return result;
}
};
//一个一个往后移
class Solution {
public:
string reverseLeftWords(string s, int n) {
int size=s.size();
if(s.empty()||n==0){
return s;
}
int count=n%size;
while(count){
char temp=s[0];
int i=0;
for(;i<size-1;i++){
s[i]=s[i+1];
}
s[i]=temp;
count--;
}
return s;
}
};
//局部逆置
class Solution {
public:
void reverseLeftWordsHelper(string &s,int start,int end){
while(start<end){
char temp=s[start];
s[start]=s[end];
s[end]=temp;
start++,end--;
}
}
string reverseLeftWords(string s, int n) {
if(s.empty()||n==0){
return s;
}
n%=s.size();
reverseLeftWordsHelper(s,0,n-1);
reverseLeftWordsHelper(s,n,s.size()-1);
reverseLeftWordsHelper(s,0,s.size()-1);
return s;
}
};