# 递归

## 1、二叉树的最大深度（104、Easy）

### 1）题目要求

3


/
9 20
/
15 7

### 2）我的解法

c++

class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL)return 0;
return max(maxDepth(root->left)+1,maxDepth(root->right)+1);
}
};


### 3）其他解法

class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == nullptr) return 0;
queue<TreeNode*> Q;
Q.push(root);
int ans = 0;
while (!Q.empty()) {
int sz = Q.size();
while (sz > 0) {
TreeNode* node = Q.front();Q.pop();
if (node->left) Q.push(node->left);
if (node->right) Q.push(node->right);
sz -= 1;
}
ans += 1;
}
return ans;
}
};



### 4）自己的优化代码

c++

class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL)return 0;
return max(maxDepth(root->left)+1,maxDepth(root->right)+1);
}
};


## 2、平衡二叉树（110、Easy）

### 1）题目要求

3
/
9 20
/
15 7

   1
/ \
2   2
/ \


3 3
/
4 4

### 2）我的解法

c++

class Solution {
public:
int height(TreeNode*root)
{
if(root==NULL)return 0;
return (max(height(root->left),height(root->right))+1);
}

bool isBalanced(TreeNode* root) {
if(root==NULL)return true;
else return (abs(height(root->left)-height(root->right))<=1&&isBalanced(root->left)&&isBalanced(root->right))?true:false;
}
};


### 3）其他解法

class Solution {
private:
// Return whether or not the tree at root is balanced while also storing
// the tree's height in a reference variable.
bool isBalancedTreeHelper(TreeNode* root, int& height) {
// An empty tree is balanced and has height = -1
if (root == NULL) {
height = -1;
return true;
}

// Check subtrees to see if they are balanced. If they are, check if the
// current node is also balanced using the heights obtained from the
// recursive calls.
int left, right;
if (isBalancedTreeHelper(root->left, left)  &&
isBalancedTreeHelper(root->right, right) &&
abs(left - right) < 2) {
// Store the current tree's height
height = max(left, right) + 1;
return true;
}
return false;
}
public:
bool isBalanced(TreeNode* root) {
int height;
return isBalancedTreeHelper(root, height);
}
};



### 4）自己的优化代码

c++

class Solution {
public:
bool isBalancedHelp(TreeNode*root,int&height)//一定要加上&
{
if(root==NULL){height=0;return true;}
else
{
int left,right;
if(isBalancedHelp(root->left,left)&&isBalancedHelp(root->right,right)&&abs(left-right)<=1)
{
height=max(left,right)+1;
return true;
}
else return false;
}
}

bool isBalanced(TreeNode* root) {
int height;
return isBalancedHelp(root,height);
}
};


## 3、二叉树的直径（543、Easy）

### 1）题目要求

      1
/ \
2   3
/ \
4   5


### 2）我的解法

c++

class Solution {
public:
int height(TreeNode*root)
{
if(root==NULL)return 0;
return (max(height(root->left),height(root->right))+1);
}
int getmax(int a,int b,int c)
{
return max(c,max(a,b));
}
int diameterOfBinaryTree(TreeNode* root) {
if(root==NULL)return 0;
return getmax(diameterOfBinaryTree(root->left),diameterOfBinaryTree(root->right),
height(root->left)+height(root->right));
}
};


### 3）其他解法

class Solution {
int ans;
int depth(TreeNode* rt){
if (rt == NULL) return 0; // 访问到空节点了，返回0
int L = depth(rt->left); // 左儿子为根的子树的深度
int R = depth(rt->right); // 右儿子为根的子树的深度
ans = max(ans, L + R + 1); // 计算d_node即L+R+1 并更新ans
return max(L, R) + 1; // 返回该节点为根的子树的深度
}
public:
int diameterOfBinaryTree(TreeNode* root) {
ans = 1;
depth(root);
return ans - 1;
}
};



### 4）自己的优化代码

c++

class Solution {
public:
int maxd=0;
int geth(TreeNode*root)//求结点高度
{
if(root==NULL)return 0;
int l=geth(root->left);
int r=geth(root->right);
maxd=max((l+r),maxd);//经过的边数
return max(l,r)+1;
}
int diameterOfBinaryTree(TreeNode* root) {
geth(root);
return maxd;
}
};


## 4、翻转二叉树（226、Easy）

### 1）题目要求

 4


/
2 7
/ \ /
1 3 6 9

 4


/
7 2
/ \ /
9 6 3 1

### 2）我的解法

c++

class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==NULL)return NULL;
TreeNode* temp=invertTree(root->left);
root->left=invertTree(root->right);
root->right=temp;
return root;
}
};


### 3）其他解法

(1)递归

public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode right = invertTree(root.right);
TreeNode left = invertTree(root.left);
root.left = right;
root.right = left;
return root;
}



(2)迭代

public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
while (!queue.isEmpty()) {
TreeNode current = queue.poll();
TreeNode temp = current.left;
current.left = current.right;
current.right = temp;
if (current.left != null) queue.add(current.left);
if (current.right != null) queue.add(current.right);
}
return root;
}



### 4）自己的优化代码

c++

class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==NULL)return NULL;
TreeNode* L=invertTree(root->left);
root->left=invertTree(root->right);
root->right=L;
return root;
}
};


## 5、合并二叉树（617、Easy）

Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7

3
/
4 5
/ \ \
5 4 7

### 2）我的解法

c++

class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
TreeNode*result=new TreeNode(-1);
if(t1!=NULL)
{
if(t2!=NULL)
{
result->val=t1->val+t2->val;
result->left=mergeTrees(t1->left,t2->left);
result->right=mergeTrees(t1->right,t2->right);
}
else result=t1;
}
else result=t2;
return result;
}
};


### 3）其他解法

（1）递归

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null)
return t2;
if (t2 == null)
return t1;
t1.val += t2.val;
t1.left = mergeTrees(t1.left, t2.left);
t1.right = mergeTrees(t1.right, t2.right);
return t1;
}
}



（2）迭代

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null)
return t2;
Stack < TreeNode[] > stack = new Stack < > ();
stack.push(new TreeNode[] {t1, t2});
while (!stack.isEmpty()) {
TreeNode[] t = stack.pop();
if (t[0] == null || t[1] == null) {
continue;
}
t[0].val += t[1].val;
if (t[0].left == null) {
t[0].left = t[1].left;
} else {
stack.push(new TreeNode[] {t[0].left, t[1].left});
}
if (t[0].right == null) {
t[0].right = t[1].right;
} else {
stack.push(new TreeNode[] {t[0].right, t[1].right});
}
}
return t1;
}
}



### 4）自己的优化代码

c++

class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(t1==NULL)return t2;
if(t2==NULL)return t1;
t1->val+=t2->val;
t1->left=mergeTrees(t1->left,t2->left);
t1->right=mergeTrees(t1->right,t2->right);
return t1;
}
};


## 6、路径总和（112、Easy）

### 1）题目要求

          5
/ \
4   8
/   / \
11  13  4
/  \      \
7    2      1


### 2）我的解法

c++

class Solution {
public:
int addsum(TreeNode* root, int sum)
{
if(root==NULL)return -100000000;
int l=0,r=0;
if(root->left==NULL&&root->right==NULL)l=root->val;
if(root->left==NULL&&root->right==NULL)r=root->val;
if(l==sum||r==sum)return sum;
else return l;
}
bool hasPathSum(TreeNode* root, int sum) {
if(root==NULL)return false;
if((root->left!=NULL&&root->right==NULL)||(root->left==NULL&&root->right!=NULL))
{
if(root->val==sum)return false;
}
}
};


### 3）其他解法

（1）递归

class Solution {
public:
bool hasPathSum(TreeNode *root, int sum) {
if (root == nullptr) {
return false;
}
if (root->left == nullptr && root->right == nullptr) {
return sum == root->val;
}
return hasPathSum(root->left, sum - root->val) ||
hasPathSum(root->right, sum - root->val);
}
};


（2）广度优先搜索

class Solution {
public:
bool hasPathSum(TreeNode *root, int sum) {
if (root == nullptr) {
return false;
}
queue<TreeNode *> que_node;
queue<int> que_val;
que_node.push(root);
que_val.push(root->val);
while (!que_node.empty()) {
TreeNode *now = que_node.front();
int temp = que_val.front();
que_node.pop();
que_val.pop();
if (now->left == nullptr && now->right == nullptr) {
if (temp == sum) return true;
continue;
}
if (now->left != nullptr) {
que_node.push(now->left);
que_val.push(now->left->val + temp);
}
if (now->right != nullptr) {
que_node.push(now->right);
que_val.push(now->right->val + temp);
}
}
return false;
}
};



### 4）自己的优化代码

c++

class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if(root==NULL)return false;
if(root->left==NULL&&root->right==NULL)return root->val==sum;
return hasPathSum(root->left,sum-root->val)||hasPathSum(root->right,sum-root->val);
}
};


### 5）学到的东西

bool类型函数也可以递归，仅在叶子结点进行真正的判断

## 7、另一个树的子树(572、Easy）

### 1）题目要求

 3
/ \


4 5
/
1 2

4
/
1 2

 3
/ \


4 5
/
1 2
/
0

4
/
1 2

### 2）我的解法

c++

class Solution {
public:
bool isequal(TreeNode* s, TreeNode* t)
{
if(s==NULL)
{
if(t==NULL)return true;
else return false;
}
else if(t==NULL)return false;
return(s->val==t->val&&isequal(s->left,t->left)&&isequal(s->right,t->right));
}
bool isSubtree(TreeNode* s, TreeNode* t) {
if(s==NULL)return false;
if(s->val==t->val)return isequal(s,t)||isSubtree(s->left,t)||isSubtree(s->right,t);//如果值相等做进一步判断
return isSubtree(s->left,t)||isSubtree(s->right,t);
}
};


### 3）其他解法

class Solution {
public:
bool check(TreeNode *o, TreeNode *t) {
if (!o && !t) return true;
if ((o && !t) || (!o && t) || (o->val != t->val)) return false;
return check(o->left, t->left) && check(o->right, t->right);
}

bool dfs(TreeNode *o, TreeNode *t) {
if (!o) return false;
return check(o, t) || dfs(o->left, t) || dfs(o->right, t);
}

bool isSubtree(TreeNode *s, TreeNode *t) {
return dfs(s, t);
}
};



class Solution {
public:
vector <int> sOrder, tOrder;
int maxElement, lNull, rNull;

void getMaxElement(TreeNode *o) {
if (!o) return;
maxElement = max(maxElement, o->val);
getMaxElement(o->left);
getMaxElement(o->right);
}

void getDfsOrder(TreeNode *o, vector <int> &tar) {
if (!o) return;
tar.push_back(o->val);
if (o->left) getDfsOrder(o->left, tar);
else tar.push_back(lNull);
if (o->right) getDfsOrder(o->right, tar);
else tar.push_back(rNull);
}

bool kmp() {
int sLen = sOrder.size(), tLen = tOrder.size();
vector <int> fail(tOrder.size(), -1);
for (int i = 1, j = -1; i < tLen; ++i) {
while (j != -1 && tOrder[i] != tOrder[j + 1]) j = fail[j];
if (tOrder[i] == tOrder[j + 1]) ++j;
fail[i] = j;
}
for (int i = 0, j = -1; i < sLen; ++i) {
while (j != -1 && sOrder[i] != tOrder[j + 1]) j = fail[j];
if (sOrder[i] == tOrder[j + 1]) ++j;
if (j == tLen - 1) return true;
}
return false;
}

bool isSubtree(TreeNode* s, TreeNode* t) {
maxElement = INT_MIN;
getMaxElement(s);
getMaxElement(t);
lNull = maxElement + 1;
rNull = maxElement + 2;

getDfsOrder(s, sOrder);
getDfsOrder(t, tOrder);

return kmp();
}
};



### 4）自己的优化代码

c++
(1)运用bf

class Solution {
public:
int lnull=-10000,rnull=-10001;
void getdfs(TreeNode* root,vector<int> &result)
{
if(!root)return ;
else result.push_back(root->val);
if(root->left)getdfs(root->left,result);
else result.push_back(lnull);
if(root->right)getdfs(root->right,result);
else result.push_back(rnull);
}
bool bf(vector<int> s,vector<int> t)
{
for(int i=0;i<s.size();i++)
{
for(int j=0;j<t.size();j++)
{
if(s[i+j]!=t[j])break;//用i+j能避免i值不对的问题
if(j==t.size()-1)return true;
}
}
return false;
}
bool isSubtree(TreeNode* s, TreeNode* t) {
vector<int> s1,t1;
getdfs(s,s1);
getdfs(t,t1);
return bf(s1,t1);
}
};


（2）运用kmp

KMP算法实例详解(易懂)

class Solution {
public:
int lnull=-10000,rnull=-10001;
void getdfs(TreeNode* root,vector<int> &result)
{
if(!root)return ;
else result.push_back(root->val);
if(root->left)getdfs(root->left,result);
else result.push_back(lnull);
if(root->right)getdfs(root->right,result);
else result.push_back(rnull);
}
bool kmp(vector<int> s,vector<int> t)
{
vector<int> next(t.size(),-1);//相同前后缀长为k+1
for (int i = 1, k = -1; i < t.size(); ++i) {
while (k != -1 && t[i-1] != t[k]) k = next[k];
next[i] = ++k;
}
int i = 0, j =0;
while(i < s.size())
{
if (s[i] == t[j]) j++;//当匹配成功，继续匹配
else
{
j=next[j];//匹配不成功，移动模式串的指针
if(j==-1)j++;//如果j==-1，模式串从头开始，目标串指针也往后移
else continue;//如果j!=-1，仅移动模式串指针，不移动目标串指针
}
i++;
if (j == t.size()) return true;
}
return false;
}
bool isSubtree(TreeNode* s, TreeNode* t) {
vector<int> s1,t1;
getdfs(s,s1);
getdfs(t,t1);
return kmp(s1,t1);
}
};


BF匹配算法，KMP算法

## 8、路径总和 III（437、Easy）

### 1）题目要求

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

  10
/  \
5   -3


/ \
3 2 11
/ \
3 -2 1

1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11

### 2）我的解法

c++

class Solution {
public:
int pasum=0;
void panduan(TreeNode* root, int sum) {
if(!root)return;
if(root->val==sum)pasum++;
panduan(root->left,sum-root->val);
panduan(root->right,sum-root->val);
}
void panduanall(TreeNode* root, int sum)
{
if(!root)return ;
panduan(root,sum);
panduanall(root->left,sum);
panduanall(root->right,sum);
}
int pathSum(TreeNode* root, int sum) {
panduanall(root,sum);
return pasum;

}
};


### 3）其他解法

1、双重递归
①先序递归遍历每个节点
②以每个节点作为起始节点DFS寻找满足条件的路径

class Solution {
public:
int ans = 0;

void dfs(TreeNode* root, int sum)
{
if(root == nullptr)
return;
sum -= root->val;
if(sum == 0)
ans++;
dfs(root->left, sum);
dfs(root->right, sum);
}

int pathSum(TreeNode* root, int sum) {
if(root == nullptr)
return ans;
dfs(root, sum);
pathSum(root->left, sum);
pathSum(root->right, sum);
return ans;
}
};



2、前缀和

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int pathSum(TreeNode root, int sum) {
// key是前缀和, value是大小为key的前缀和出现的次数
Map<Integer, Integer> prefixSumCount = new HashMap<>();
// 前缀和为0的一条路径
prefixSumCount.put(0, 1);
// 前缀和的递归回溯思路
return recursionPathSum(root, prefixSumCount, sum, 0);
}

/**
* 前缀和的递归回溯思路
* 从当前节点反推到根节点(反推比较好理解，正向其实也只有一条)，有且仅有一条路径，因为这是一棵树
* 如果此前有和为currSum-target,而当前的和又为currSum,两者的差就肯定为target了
* 所以前缀和对于当前路径来说是唯一的，当前记录的前缀和，在回溯结束，回到本层时去除，保证其不影响其他分支的结果
* @param node 树节点
* @param prefixSumCount 前缀和Map
* @param target 目标值
* @param currSum 当前路径和
* @return 满足题意的解
*/
private int recursionPathSum(TreeNode node, Map<Integer, Integer> prefixSumCount, int target, int currSum) {
// 1.递归终止条件
if (node == null) {
return 0;
}
// 2.本层要做的事情
int res = 0;
// 当前路径上的和
currSum += node.val;

//---核心代码
// 看看root到当前节点这条路上是否存在节点前缀和加target为currSum的路径
// 当前节点->root节点反推，有且仅有一条路径，如果此前有和为currSum-target,而当前的和又为currSum,两者的差就肯定为target了
// currSum-target相当于找路径的起点，起点的sum+target=currSum，当前点到起点的距离就是target
res += prefixSumCount.getOrDefault(currSum - target, 0);
// 更新路径上当前节点前缀和的个数
prefixSumCount.put(currSum, prefixSumCount.getOrDefault(currSum, 0) + 1);
//---核心代码

// 3.进入下一层
res += recursionPathSum(node.left, prefixSumCount, target, currSum);
res += recursionPathSum(node.right, prefixSumCount, target, currSum);

// 4.回到本层，恢复状态，去除当前节点的前缀和数量
prefixSumCount.put(currSum, prefixSumCount.get(currSum) - 1);
return res;
}
}



### 4）自己的优化代码

c++

class Solution {
public:
int pasum=0;
void panduan(TreeNode* root, int sum) {
if(!root)return;
if(root->val==sum)pasum++;
panduan(root->left,sum-root->val);
panduan(root->right,sum-root->val);
}
int pathSum(TreeNode* root, int sum) {
if(!root)return 0;
panduan(root,sum);
pathSum(root->left,sum);
pathSum(root->right,sum);
return pasum;

}
};


## 9、二叉树的最小深度（111、Easy）

### 2）我的解法

c++

class Solution {
public:
int getmin(TreeNode* root)
{
int left=9999,right=9999;
if(!root)return 9999;
if(!root->left&&!root->right)return 1;
left=getmin(root->left)+1;
right=getmin(root->right)+1;
return min(left,right);
}
int minDepth(TreeNode* root) {
if(!root)return 0;
return getmin(root);

}
};


### 3）其他解法

（1）递归

class Solution {
public:
int minDepth(TreeNode* root) {
if (root == nullptr) return 0;

int left = minDepth(root->left);
int right = minDepth(root->right);

if (root->left == nullptr || root->right == nullptr){
return left == 0 ? right+1 : left +1;
} else{
return min(left, right) + 1;
}
}
};


（2）深度优先搜索迭代

class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
else {
}

int min_depth = Integer.MAX_VALUE;
while (!stack.isEmpty()) {
Pair<TreeNode, Integer> current = stack.pollLast();
root = current.getKey();
int current_depth = current.getValue();
if ((root.left == null) && (root.right == null)) {
min_depth = Math.min(min_depth, current_depth);
}
if (root.left != null) {
stack.add(new Pair(root.left, current_depth + 1));
}
if (root.right != null) {
stack.add(new Pair(root.right, current_depth + 1));
}
}
return min_depth;
}
}



（3）广度优先搜索迭代

class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
else {
}

int current_depth = 0;
while (!stack.isEmpty()) {
Pair<TreeNode, Integer> current = stack.poll();
root = current.getKey();
current_depth = current.getValue();
if ((root.left == null) && (root.right == null)) {
break;
}
if (root.left != null) {
stack.add(new Pair(root.left, current_depth + 1));
}
if (root.right != null) {
stack.add(new Pair(root.right, current_depth + 1));
}
}
return current_depth;
}
}


### 4）自己的优化代码

c++

class Solution {
public:
int minDepth(TreeNode* root) {
int left=9999,right=9999;
if(!root)return 0;
if(!root->left&&!root->right)return 1;

left=minDepth(root->left)+1;
right=minDepth(root->right)+1;

if(left==1)left=9999;
if(right==1)right=9999;
return min(left,right);

}
};


## 10、对称二叉树（101、Easy）

### 1）题目要求

1


/
2 2
/ \ /
3 4 4 3

1


/
2 2
\
3 3

### 2）我的解法

c++

class Solution {
public:
bool isduichen(TreeNode*t1,TreeNode*t2)
{
if(!t1)
{
if(!t2)return true;
else return false;
}
else
{
if(!t2)return false;
}
return (t1->val==t2->val&&isduichen(t1->left,t2->right)&&isduichen(t1->right,t2->left));
}
bool isSymmetric(TreeNode* root) {
if(!root)return true;
return isduichen(root->left,root->right);
}
};


### 3）其他解法

(1)递归

class Solution {
public:
bool check(TreeNode *p, TreeNode *q) {
if (!p && !q) return true;
if (!p || !q) return false;
return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
}

bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};



（2）迭代

「方法一」中我们用递归的方法实现了对称性的判断，那么如何用迭代的方法实现呢？首先我们引入一个队列，这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值（队列中每两个连续的结点应该是相等的，而且它们的子树互为镜像），然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时，或者我们检测到树不对称（即从队列中取出两个不相等的连续结点）时，该算法结束。

class Solution {
public:
bool check(TreeNode *u, TreeNode *v) {
queue <TreeNode*> q;
q.push(u); q.push(v);
while (!q.empty()) {
u = q.front(); q.pop();
v = q.front(); q.pop();
if (!u && !v) continue;
if ((!u || !v) || (u->val != v->val)) return false;

q.push(u->left);
q.push(v->right);

q.push(u->right);
q.push(v->left);
}
return true;
}

bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};



### 4）自己的优化代码

c++
1、递归

class Solution {
public:
bool isduichen(TreeNode*t1,TreeNode*t2)
{
if(!t1&&!t2)return true;
if(!t1||!t2)return false;
return (t1->val==t2->val&&isduichen(t1->left,t2->right)&&isduichen(t1->right,t2->left));
}
bool isSymmetric(TreeNode* root) {
return isduichen(root,root);
}
};


2、迭代

class Solution {
public:
bool isduichen(TreeNode*t1,TreeNode*t2)
{
queue<TreeNode*> q;
q.push(t1);q.push(t2);
while(!q.empty())
{
TreeNode*u=q.front();q.pop();
TreeNode*v=q.front();q.pop();
if(!u&&!v)continue;
if(!u||!v||u->val!=v->val)return false;
q.push(u->left);
q.push(v->right);

q.push(u->right);
q.push(v->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return isduichen(root,root);
}
};


## 11、左叶子之和（404、Easy）

### 1）题目要求

（这个题号是一个很有意义的数字呢）

3


/
9 20
/
15 7

### 2）我的解法

c++

class Solution {
public:
int sum(TreeNode*root)
{
if(!root)return 0;
if(!root->left&&!root->right)return root->val;
int l=sum(root->left);
int r=0;
if(root->right&&!root->right->left&&!root->right->right)r=0;
else r=sum(root->right);

return l+r;
}
int sumOfLeftLeaves(TreeNode* root) {
if(!root)return 0;
if(!root->left&&!root->right)return 0;
return sum(root);

}
};


### 3）其他解法

1、递归


class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root == NULL) return 0;
if(root->left!=NULL&&root->left->right==NULL&&root->left->left==NULL) return sumOfLeftLeaves(root->right)+root->left->val;
return sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);
}
};



2、迭代

public int sumOfLeftLeaves(TreeNode root) {
if (root == null) {
return 0;
}
stack.push(new Pair<>(root, false));

int sum = 0;
Boolean flag;//标识是否为左节点
while (!stack.isEmpty()) {
Pair<TreeNode, Boolean> pair = stack.pop();
root = pair.getKey();
flag = pair.getValue();
if (flag && root.left == null && root.right == null) {
sum += root.val;
}
if (root.left != null) {
stack.push(new Pair<>(root.left, true));
}
if (root.right != null) {
stack.push(new Pair<>(root.right, false));
}
}
return sum;
}



### 4）自己的优化代码

c++

class Solution {
public:

int sumOfLeftLeaves(TreeNode* root) {
if(!root)return 0;
if(root->left &&!root->left->left&&!root->left->right)return root->left->val+sumOfLeftLeaves(root->right);
return sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);
}
};


## 12、最长同值路径（687、Easy）

### 1）题目要求

          5
/ \
4   5
/ \   \
1   1   5


2

          1
/ \
4   5
/ \   \
4   4   5


2

### 2）我的解法

c++

class Solution {
public:
int findnode(TreeNode*root,int target,bool tag)
{
if(!root)return 0;
if(tag){//判断是否作为根节点
if(root->val==target)return 1+findnode(root->left,target,false)+findnode(root->right,target,false);
return 0;
}
else{
if(root->val==target)return 1+max(findnode(root->left,target,false),
findnode(root->right,target,false));
return 0;
}
}
int getmax(int a,int b,int c)
{
return max(a,max(b,c));
}
int longestUnivaluePath(TreeNode* root) {
if(!root)return 0;
return getmax(findnode(root,root->val,true)-1,longestUnivaluePath(root->left),
longestUnivaluePath(root->right));
}
};


### 3）其他解法

class Solution {
int ans;
public int longestUnivaluePath(TreeNode root) {
ans = 0;
arrowLength(root);
return ans;
}
public int arrowLength(TreeNode node) {
if (node == null) return 0;
int left = arrowLength(node.left);
int right = arrowLength(node.right);
int arrowLeft = 0, arrowRight = 0;
if (node.left != null && node.left.val == node.val) {
arrowLeft += left + 1;
}
if (node.right != null && node.right.val == node.val) {
arrowRight += right + 1;
}
ans = Math.max(ans, arrowLeft + arrowRight);
return Math.max(arrowLeft, arrowRight);
}
}



### 4）自己的优化代码

c++

class Solution {
public:
int ans;
int asroot(TreeNode*root)
{
if(!root)return 0;
int L=asroot(root->left),R=asroot(root->right);//递归放前面
if(root->left&&root->left->val==root->val)
{
L=1+L;
}
else L=0;
if(root->right&&root->right->val==root->val)
{
R=1+R;
}
else R=0;
ans=max(ans,L+R);
return max(L,R);

}
int longestUnivaluePath(TreeNode* root) {
ans=0;
asroot(root);
return ans;
}
};


## 1）题目要求

2
/
2 5
/
5 7

2
/
2 2

### 2）我的解法

c++

class Solution {
public:
long long min[2]={4147483647,4147483647};
void findnode(TreeNode*root)
{
if(!root)return ;
if(root->val<=min[0])min[0]=root->val;
else if(root->val<=min[1])min[1]=root->val;
findnode(root->left);
findnode(root->right);

}
int findSecondMinimumValue(TreeNode* root) {
findnode(root);
return min[1]==4147483647?-1:min[1];
}
};


### 3）其他解法

1. 首先分析题意：每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话，那么这个节点的值不大于它的子节点的值。也就是说当前节点的值是以当前节点为根节点的二叉树中的最小值。
2. 同理，当前节点的左子节点的值是左子树中的最小值，右子节点的值是右子树中的最小值。注意当前如果左右子节点和根节点的值相同时，不能直接进行判断，因为左右子树中可能会存在第二小的值。此时，通过递归来找到解。
3. 即，如果当前节点的值和左子节点的值相同，那么递归的去找左子树中的第二小的节点；如果当前节点的值和右子节点的值相同，那么递归的去找右子树中的第二小的节点。
4. 左右子树递归完成后，仅考虑当前三个节点即可得出结果。若三个节点的值相等，则说明没有第二小节点，否则肯定能找到。
/**
* 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 findSecondMinimumValue(TreeNode* root) {
if(!root || !root->left || !root->right) return -1;//空节点或不满足题意

int left=root->left->val,right=root->right->val;

//若根节点和左节点值相同，则递归找左子树的第二小节点
if(root->val==root->left->val) left=findSecondMinimumValue(root->left);
//若根节点和右节点值相同，则递归找右子树的第二小节点
if(root->val==root->right->val) right=findSecondMinimumValue(root->right);

//若根节点等于左右子树的第二小节点返回-1
if(root->val==left && root->val==right) return -1;

//根据当前的根、左右节点的值继续判断
int min_lr=min(left,right);
if(root->val<min_lr) return min_lr;//根节点小于最小值，返回最小值
else return max(left,right);//根节点等于最小值，返回最大值
}

};



### 4）自己的优化代码

c++

class Solution {
public:
int findSecondMinimumValue(TreeNode* root) {
if(!root||!root->left|!root->right)return -1;

int L=root->left->val,R=root->right->val;

if(root->val==L)L=findSecondMinimumValue(root->left);//找到左子树中第二小的，之后与右节点比较
if(root->val==R)R=findSecondMinimumValue(root->right);//找到右子树中第二小的，之后与左节点比较

int smin=min(L,R);
int smax=max(L,R);
if(root->val<smin)return smin;
else {
if(root->val<smax)return smax;
else return -1;
}

}
};


## 14、打家劫舍 III（337、Medium）

### 1）题目要求

 3
/ \


2 3
\ \
3 1

 3
/ \


4 5
/ \ \
1 3 1

### 2）我的解法

c++
（1）暴力：（超时）

class Solution {
public:

int find(TreeNode*root,bool tag)
{
if(!root)return 0;
if(tag)return root->val+find(root->left,false)+find(root->right,false);
//当抢了当前房子，它的两个子结点就不能抢了
int left=max(find(root->left,false),find(root->left,true));
int right=max(find(root->right,false),find(root->right,true));
return left+right;
}
int rob(TreeNode* root) {
return max(find(root,true),find(root,false));

}
};


（2）动态规划：（通过）

class Solution {
public:
unordered_map<TreeNode*,int> dp;
//以下为动态规划的状态转移方程
//int child=dp[i->left]+dp[i->right];
//int grandchild=dp[i->left->left]+dp[i->left->right]
//+dp[i->right->left]+dp[i->right->right]
//dp[i]=max(child,grandchild+i);
void find(TreeNode*root)
{
if(!root){dp[root]=0;return ;}
find(root->left);
find(root->right);//后序遍历
int child=dp[root->left]+dp[root->right];
int lchild=0,rchild=0;
if(root->left)lchild=dp[root->left->left]+dp[root->left->right];
if(root->right)rchild=dp[root->right->left]+dp[root->right->right];
dp[root]=max(lchild+rchild+root->val,child);
return;
}
int rob(TreeNode* root) {
find(root);
return dp[root];
}
};


### 3）其他解法

public int rob(TreeNode root) {
if (root == null) return 0;

int money = root.val;
if (root.left != null) {
money += (rob(root.left.left) + rob(root.left.right));
}

if (root.right != null) {
money += (rob(root.right.left) + rob(root.right.right));
}

return Math.max(money, rob(root.left) + rob(root.right));
}



public int rob(TreeNode root) {
HashMap<TreeNode, Integer> memo = new HashMap<>();
return robInternal(root, memo);
}

public int robInternal(TreeNode root, HashMap<TreeNode, Integer> memo) {
if (root == null) return 0;
if (memo.containsKey(root)) return memo.get(root);
int money = root.val;

if (root.left != null) {
money += (robInternal(root.left.left, memo) + robInternal(root.left.right, memo));
}
if (root.right != null) {
money += (robInternal(root.right.left, memo) + robInternal(root.right.right, memo));
}
int result = Math.max(money, robInternal(root.left, memo) + robInternal(root.right, memo));
memo.put(root, result);
return result;
}



（相当于打家劫舍1里面的滚动数组）

public int rob(TreeNode root) {
int[] result = robInternal(root);
return Math.max(result[0], result[1]);
}

public int[] robInternal(TreeNode root) {
if (root == null) return new int[2];
int[] result = new int[2];

int[] left = robInternal(root.left);
int[] right = robInternal(root.right);

result[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
result[1] = left[0] + right[0] + root.val;

return result;
}



### 4）自己的优化代码

c++

 */
class Solution {
public:
vector<int> find(TreeNode*root)
{
if(!root)return {0,0};

vector<int> L=find(root->left);
vector<int> R=find(root->right);

return {L[1]+R[1]+root->val,max(L[0],L[1])+max(R[0],R[1])};
}
int rob(TreeNode* root) {
vector<int> result=find(root);
return max(result[0],result[1]);
}
};


# 层次遍历

## 1、二叉树的层平均值（637、Easy）

3
/
9 20
/
15 7

### 2）我的解法

c++

class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double> result;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
vector<TreeNode*> temp;
double sum=0;
while(!q.empty()){
if(!q.front()){q.pop();continue;}
temp.push_back(q.front());
sum+=q.front()->val;
q.pop();
}
if(temp.size()==0)break;
result.push_back(sum/temp.size());
for(int i=0;i<temp.size();i++)
{
q.push(temp[i]->left);
q.push(temp[i]->right);
}
}
return result;
}
};


### 3）其他解法

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List < Double > averageOfLevels(TreeNode root) {
List < Integer > count = new ArrayList < > ();
List < Double > res = new ArrayList < > ();
average(root, 0, res, count);
for (int i = 0; i < res.size(); i++)
res.set(i, res.get(i) / count.get(i));
return res;
}
public void average(TreeNode t, int i, List < Double > sum, List < Integer > count) {
if (t == null)
return;
if (i < sum.size()) {
sum.set(i, sum.get(i) + t.val);
count.set(i, count.get(i) + 1);
} else {
}
average(t.left, i + 1, sum, count);
average(t.right, i + 1, sum, count);
}
}



public List<Double> averageOfLevels(TreeNode root){
List<Double> res = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
while(!queue.isEmpty()){
//外层while循环用于遍历层，判断的逻辑是：只要queue非空，那就证明至少还有一层没有遍历到
long sum = 0;
long count = 0;
Queue<TreeNode> temp = new LinkedList<>();
while(!queue.isEmpty()){
//内层while循环用于遍历本层的每个结点
TreeNode n = queue.remove();//一个结点出队列
sum += n.val;
count++;
//将当前结点的左右孩子加入队列temp
if(n.left!=null){
}
if(n.right!=null){
}
}
/*
* 本层结点遍历结束,queue中为空，temp中保存的是下一层的结点;
* 将temp传给queue，外层while循环遍历下一层结点
*/
queue = temp;
//将本层的平均值加入res数组
}
return res;
}


### 4）自己的优化代码

c++

class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double> result;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
vector<TreeNode*> temp;//保存上一层
double sum=0;
while(!q.empty()){
if(!q.front()){q.pop();continue;}
temp.push_back(q.front());
sum+=q.front()->val;
q.pop();
}
if(temp.size()==0)break;
result.push_back(sum/temp.size());
for(int i=0;i<temp.size();i++)
{
q.push(temp[i]->left);
q.push(temp[i]->right);
}
}
return result;
}
};


## 2、找树左下角的值（513、Medium）

### 1）题目要求

2


/
1 3

1

    1
/ \
2   3
/   / \
4   5   6
/
7


7

### 2）我的解法

c++

class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
int last=0;
while(!q.empty())
{
vector<TreeNode*> temp;
while(!q.empty())
{
if(!q.front()){q.pop();continue;}
temp.push_back(q.front());
q.pop();
}
if(temp.size()==0)break;
last=temp[0]->val;
for(int i=0;i<temp.size();i++)
{
q.push(temp[i]->left);
q.push(temp[i]->right);
}
}
return last;

}
};


### 3）其他解法

//方法1：迭代
public int findBottomLeftValue1(TreeNode root) {
//层序遍历
Queue<TreeNode> queue = new LinkedList<>();
int res = 0;
while (!queue.isEmpty()) {
int count = queue.size();
//将每层左边第一个作为结果
res = queue.peek().val;
while (count-- > 0) {
TreeNode cur = queue.poll();
if (cur.left != null) {
}
if (cur.right != null) {
}
}
}
return res;
}




//方法2：递归
class Solution{
int maxDepth = -1, res = -1;

public int findBottomLeftValue2(TreeNode root) {
helper(root, 0);
return res;
}

private void helper(TreeNode root, int depth) {
if (root == null) return;
helper(root.left, depth + 1);
//判断是否是最大深度
if (depth > maxDepth) {
maxDepth = depth;
res = root.val;
}
helper(root.right, depth + 1);
}
}



# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
queue = [root]
while queue:
node = queue.pop(0)
if node.right:  # 先右后左
queue.append(node.right)
if node.left:
queue.append(node.left)
return node.val



### 4）自己的优化代码

c++

class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
int last=0;
while(!q.empty())
{
TreeNode*cur=q.front();
q.pop();
if(!cur)continue;
last=cur->val;
q.push(cur->right);//先右后左
q.push(cur->left);
}
return last;

}
};


# 前中后序遍历

## 1、二叉树的前序遍历（144、Medium）

1

2
/
3

### 2）我的解法

1、递归

class Solution {
private List<Integer> result=new ArrayList<>();
public void getResult(TreeNode root){
if(root==null)return;
getResult(root.left);
getResult(root.right);
}
public List<Integer> preorderTraversal(TreeNode root) {
getResult(root);
return result;
}
}


2、迭代

class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Stack<TreeNode> s=new Stack();
if(root==null)return result;

TreeNode t=root;
while(true){

if(t.right!=null)s.push(t.right);

if(t.left!=null)t=t.left;
else {
if(s.empty())break;
t=s.peek();
s.pop();
}

}
return result;

}
}


### 3）其他解法

1、迭代

class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) {
return output;
}

while (!stack.isEmpty()) {
TreeNode node = stack.pollLast();
if (node.right != null) {
}
if (node.left != null) {
}
}
return output;
}
}



### 4）自己的优化代码

class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Stack<TreeNode> s=new Stack();
if(root==null)return result;
s.push(root);
TreeNode t=root;
while(!s.empty()){
t=s.peek();
s.pop();

if(t.right!=null)s.push(t.right);

if(t.left!=null)s.push(t.left);

}
return result;

}
}


### 5）学到的东西

java 中栈的使用： java stack的详细实现分析

## 2、二叉树的中序遍历（94、Medium）

1

2
/
3

### 2）我的解法

1、递归

class Solution {
private List<Integer> result=new ArrayList<>();
public void getResult(TreeNode root){
if(root==null)return ;
getResult(root.left);
getResult(root.right);
}
public List<Integer> inorderTraversal(TreeNode root) {
getResult(root);
return result;
}
}


2、迭代

class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Map<TreeNode,Boolean> map=new HashMap<>();
Stack<TreeNode> s=new Stack();
if(root==null)return result;
TreeNode t=root;
while(true){
while(true){
if(map.containsKey(t))break;//如果已经入过栈，跳出
if(t.left==null){//如果左节点为空，入栈右结点后跳出
if(t.right!=null)s.push(t.right);
break;
}
else {//入栈自身和右结点，访问左结点
if(t.right!=null)s.push(t.right);
map.put(t,true);s.push(t);t=t.left;
}
}
if(s.empty())break;
t=s.peek();
s.pop();

}
return result;
}
}


### 3）其他解法

class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Deque<TreeNode> stk = new LinkedList<TreeNode>();
while (root != null || !stk.isEmpty()) {
while (root != null) {
stk.push(root);
root = root.left;
}
root = stk.pop();
root = root.right;
}
return res;
}
}



### 4）自己的优化代码

class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Stack<TreeNode> s=new Stack();
if(root==null)return result;
TreeNode t=root;
while(t!=null||!s.empty()){
while(t!=null){
s.push(t);
t=t.left;
}
t=s.pop();
t=t.right;

}
return result;
}
}


## 3、二叉树的后序遍历（145、Medium）

1

2
/
3

### 2）我的解法

1、递归

class Solution {
private List<Integer> result=new ArrayList<>();
public void getResult(TreeNode root){
if(root==null)return ;
getResult(root.left);
getResult(root.right);
}
public List<Integer> postorderTraversal(TreeNode root) {
getResult(root);
return result;
}
}


2、迭代

class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Map<TreeNode,Boolean> map=new HashMap<>();
Stack<TreeNode> s=new Stack<>();
TreeNode t=root;
while(t!=null||!s.empty()){
while(t!=null){
s.push(t);
t=t.left;
}
t=s.peek();
if(t.right==null||map.containsKey(t.right)){
s.pop();
map.put(t,true);
t=null;
}
else t=t.right;
}
return result;
}
}



### 3）其他解法

1、官方的神奇解法。。。

class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return output;
}

while (!stack.isEmpty()) {
TreeNode node = stack.pollLast();
if (node.left != null) {
}
if (node.right != null) {
}
}
return output;
}
}


### 4）自己的优化代码

class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Map<TreeNode,Boolean> map=new HashMap<>();
Stack<TreeNode> s=new Stack<>();
TreeNode t=root;
while(t!=null||!s.empty()){
while(t!=null){
s.push(t);
t=t.left;
}
t=s.peek();
if(t.right==null||map.containsKey(t.right)){
s.pop();
map.put(t,true);
t=null;
}
else t=t.right;
}
return result;
}
}



### 5）学到的东西

• 点赞
• 评论
• 分享
x

海报分享

扫一扫，分享海报

• 收藏
• 手机看

分享到微信朋友圈

x

扫一扫，手机阅读

• 打赏

打赏

波仔头

你的鼓励将是我创作的最大动力

C币 余额
2C币 4C币 6C币 10C币 20C币 50C币
• 一键三连

点赞Mark关注该博主, 随时了解TA的最新博文
08-13 460

10-28 776
11-06 38
10-20
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试