翻转树
https://leetcode-cn.com/problems/invert-binary-tree/submissions/
根据翻转树的特征,我们可以发现翻转树就是将每个节点的左子树和右子树调换,那么递归处理每个节点,定义中间变量,将每个节点的左右指针分别指向右子树和左子树。
public TreeNode invertTree(TreeNode root) {
if(root == null)
return null;
TreeNode cur = root.left;
root.left = root.right;
root.right = cur;
invertTree(root.left);
invertTree(root.right);
return root;
}
合并二叉树
https://leetcode-cn.com/problems/merge-two-binary-trees/
根据题意我们可以发现,如果两个节点都不为空时,将两个节点的值合并,否则当一个节点不为空时,可以直接将该节点作为合并树的节点。
根据这一特点,我们不难写出以下递归退出条件:
当两个节点都为空时,返回null
当一个节点为空时,返回另一个节点;
只有当两个节点都不为空时,才继续遍历下去。
class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if(t1 == null && t2 == null)return null;
if(t1 == null)return t2;
if(t2 == null)return t1;
TreeNode root = new TreeNode(t1.val + t2.val);
root.left = mergeTrees(t1.left,t2.left);
root.right = mergeTrees(t1.right,t2.right);
return root;
}
}
路径总和
https://leetcode-cn.com/problems/path-sum/
根据题意得,只有根节点递归至叶子节点且路径和与sum相等时,才返回真。
那么就分别判断根节点的左右子树,没递归到一个节点就减去该节点的值
直到递归到叶子节点且叶子节点的值与剩下的值相等(路径和等于sum)
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null)return false;
if(root.left == null && root.right == null) {
if(sum == root.val)return true;
else return false;
}
return hasPathSum(root.left,sum - root.val) || hasPathSum(root.right,sum - root.val);
}
}
路径总和 III
https://leetcode-cn.com/problems/path-sum-iii/
(以树的每一个节点做入口) <-> 双重递归
双重递归,思路其实比较清晰,就是以每个节点为开始,分别求以当前节点为起始点的路径中,是否有等于sum的路径和,如果有,就记录一下。
curPathSum(root,sum)的作用就是以当前节点开始求出路径和中是否有满足条件的个数。curPathSum(root,sum) 的路径和一直递归到叶子节点,因为树中的值有正有负,不能因为路径和<0就终止递归。
但是由题意可以看出,这个路径和可以不是从根节点开始的,可以从中间开始,那么就分别求当前左右子树的路径和,最后将三三者汇总。
但是这种解法相当于对树中的每个节点都做一次路径和,效率不高。
class Solution {
public int pathSum(TreeNode root, int sum) {
if(root == null) return 0;
int res = curPathSum(root,sum) + pathSum(root.left,sum) + pathSum(root.right,sum);
return res;
}
private int curPathSum(TreeNode root,int sum) {
if(root == null) return 0;
int res = 0;
if(root.val == sum)res++;
res += curPathSum(root.left,sum - root.val) + curPathSum(root.right,sum - root.val);
return res;
}
}
另一个树的子树
https://leetcode-cn.com/problems/subtree-of-another-tree/
和路径总和 III的解法思路类似。
(以树的每一个节点做入口) <-> 双重递归
s树中的每个节点,都有可能做为s子树的根节点与t的根节点相同。
hasSubtree(TreeNode s, TreeNode t)具体判断了两棵树是否是具有相同结构和节点值的子树。
isSubtree(TreeNode s, TreeNode t)递归地将当前节点,当前节点的左子树,当前节点的右子树分别做了判断。
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if(s == null)return false;
return hasSubtree(s,t) || isSubtree(s.left,t) || isSubtree(s.right,t);
}
private boolean hasSubtree(TreeNode s, TreeNode t) {
if(s == null && t == null)return true;
if(s == null || t == null)return false;
if(s.val != t.val)return false;
return hasSubtree(s.left,t.left) && hasSubtree(s.right,t.right);
}
}
左叶子之和
https://leetcode-cn.com/problems/sum-of-left-leaves/submissions/
判断左叶子节点之和,最好在父节点判断,如果到了叶子节点再判断时就无法确定该节点到底是左还是右。
下面两种方法哪个顺手用拿个。
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
int[] res = {0};
sumOfLeftLeaves(root,res);
return res[0];
}
private void sumOfLeftLeaves(TreeNode node,int[] res) {
if(node == null) return;
if(isLeaf(node.left)) res[0] += node.left.val;
sumOfLeftLeaves(node.left,res);
sumOfLeftLeaves(node.right,res);
}
private boolean isLeaf(TreeNode node) {
if(node == null) return false;
return node.left == null && node.right == null;
}
}
另一种解法:
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null)return 0;
if(isLeaf(root.left)) return root.left.val + sumOfLeftLeaves(root.right);
return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);
}
private boolean isLeaf(TreeNode node) {
if(node == null) return false;
return node.left == null && node.right == null;
}
}
对称二叉树
https://leetcode-cn.com/problems/symmetric-tree/submissions/
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null)return true;
return (isSymmetric(root.left,root.right));
}
private boolean isSymmetric(TreeNode left,TreeNode right) {
if(left == null && right == null)return true;
if(left == null || right == null)return false;
if(left.val != right.val)return false;
return isSymmetric(left.right,right.left) && isSymmetric(left.left,right.right);
}
}
最长同值路径
https://leetcode-cn.com/problems/longest-univalue-path/
具体思路是根据根节点来判断左右子节点是否和根节点相等,如果相等则表示是一个路径,否则路径不是一个路径。findPath的返回值表示子节点(左子右子中选一个较长的)路径中的最长路径。
class Solution {
public int longestUnivaluePath(TreeNode root) {
int[] res = {0};
findPath(root,res);
return res[0];
}
private int findPath(TreeNode root,int[] res) {
if(root == null) return 0;
int left = findPath(root.left,res);
int right = findPath(root.right,res);
int leftPath = root.left != null && root.left.val == root.val ? left + 1 : 0;
int rightPath = root.right != null && root.right.val == root.val ? right + 1 : 0;
res[0] = Math.max(res[0],leftPath + rightPath);
return Math.max(leftPath,rightPath);
}
}