树的一些常见的递归
树的递归问题在面试的过程中也是比较常见,下面对最近刷题过程中遇到的一些树的递归问题进行一个小小的总结,以后随着刷题量的增加,还是会继续在本博客中添加新的内容。
对称树问题:这是一个easy类型的题目,也就是说比较简单的题目,当时我做的时候用的方法很蠢,虽然也AC了,但是花了两毫秒,对这个问题而言是很慢的。题目的描述如下:
101. Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
下面是两次提交的结果:
第一次用的蠢方法:
class Solution {
List<Integer> list1 = new ArrayList();
List<Integer> list2 = new ArrayList();
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
if(root.left == null && root.right == null)return true;
if(root.left == null || root.right == null) return false;
pretravel1(root.left);
pretravel2(root.right);
return list1.equals(list2);
}
void pretravel1(TreeNode root){
Integer x = (root != null)?root.val:null;
list1.add(x);
if(root == null) return;
else{
pretravel1(root.left);
pretravel1(root.right);
}
}
void pretravel2(TreeNode root){
Integer x = (root != null)?root.val:null;
list2.add(x);
if(root == null) return;
else{
pretravel2(root.right);
pretravel2(root.left);
}
}
}
第二次用的稍微好一点的方法:
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return symmetric(root.left,root.right);
}
public boolean symmetric(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 symmetric(left.left,right.right) && symmetric(right.left,left.right);
}
}
Path Sum
下面是另一个关于递归的案例
112. Path Sum,这个也是比较简单的例子,我也是尽可能用最短的代码实现这个问题,下面是描述:
AC代码如下:
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null) return false;
if(root.left == null && root.right == null && root.val == sum)return true;
return hasPathSum(root.left,sum-root.val) || hasPathSum(root.right,sum-root.val);
}
}
这里的思想有点类似于分治的思想吧,要想得到一条值为sum的路径,这里减去root对应的值之外,两个子树只需要任意一个完成sum-root.val
的任务就行了,然后一步一步把任务分发下去,直到到了叶子节点,如果叶子节点的值和剩下的sum值相等,就找到了一条路径。
这里犯了一个小错误,之前提交的错误代码是这样子的:
WA代码如下:
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null && sum == 0)return true;
if(root == null) return false;
return hasPathSum(root.left,sum-root.val) || hasPathSum(root.right,sum-root.val);
}
}
错就错在我把 root = null, sum = 0 ,这种情况直接忽视了,而这种情况恰好又是递归结束的标记,我改进的方式是:直接在递归结束的标记那儿改在叶子节点,问题就解决了。
Binary Tree Paths
接着来个递归,且看 257. Binary Tree Paths,这道题我看似懂了,但是感觉又没有懂,总给我似懂非懂的感觉,题目描述如下:
如果放在以前,我可能会用后序遍历非递归来解决这个问题。现在的话,感觉递归能做的就不想用代码量巨大的后序遍历非递归,能简单就简单点。AC代码如下:
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList();
if(root == null)return res;
if(root.left == null && root.right == null){
res.add(String.valueOf(root.val));
return res;
}
List<String> left = binaryTreePaths(root.left);
for(int i=0; i<left.size(); i++)
res.add(String.valueOf(root.val)+"->"+left.get(i));
List<String> right = binaryTreePaths(root.right);
for(int i=0; i<right.size(); i++)
res.add(String.valueOf(root.val)+"->"+right.get(i));
return res;
}
}
这道题的解题思路,可以从代码中看出来,就不再赘述了,实在不懂的话,可以自己画一棵树跑一遍执行过程。