二叉树-路径(前序)
Posted naonaoling
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树-路径(前序)相关的知识,希望对你有一定的参考价值。
112. 路径总和
1 class Solution { 2 public boolean hasPathSum(TreeNode root, int sum) { 3 if(root==null){ 4 return false; 5 } 6 if(sum==root.val && root.left==null && root.right==null){ //有个叶子结点的约束 7 return true; 8 } 9 return hasPathSum(root.left, sum-root.val) 10 || hasPathSum(root.right, sum-root.val); 11 } 12 }
113. 路径总和 II 面试题34. 二叉树中和为某一值的路径
1 class Solution { 2 public List<List<Integer>> pathSum(TreeNode root, int sum) { 3 List<List<Integer>> res = new ArrayList<>(); 4 // if(root==null){ 5 // return res; 6 // } 7 findPath(root, sum, new ArrayList<>(), res); 8 return res; 9 } 10 public void findPath(TreeNode node, int sum, List<Integer> cur, List<List<Integer>> res){ 11 if(node==null){ 12 return; 13 } 14 cur.add(node.val); 15 if(node.val==sum && node.left==null && node.right==null){ 16 res.add(cur); 17 return; 18 } 19 findPath(node.left, sum-node.val, new ArrayList<>(cur), res); 20 findPath(node.right, sum-node.val, new ArrayList<>(cur), res); 21 } 22 }
1 class Solution { 2 public List<List<Integer>> pathSum(TreeNode root, int sum) { 3 List<List<Integer>> res = new ArrayList<>(); 4 // if(root==null){ 5 // return res; 6 // } 7 findPath(root, sum, new Stack<>(), res); 8 return res; 9 } 10 public void findPath(TreeNode node, int sum, Stack<Integer> cur, List<List<Integer>> res){ 11 if(node==null){ 12 return; 13 } 14 cur.push(node.val); 15 if(node.val==sum && node.left==null && node.right==null){ 16 res.add(new ArrayList<>(cur)); 17 // return; //加上return会有问题,会导致这个结点不被pop 18 } 19 // 可以加入左右子是否为空的判断,但加不加都行,反正进到函数里面也会判空 20 findPath(node.left, sum-node.val, cur, res); 21 findPath(node.right, sum-node.val, cur, res); 22 cur.pop(); 23 } 24 }
注:思路1比较好想,但是比较费空间;思路2和cousin那道题很像,注意对比理解
(1)找到路径就放入res;否则找左右子,找完左右子,pop出当前结点==>也就是以这个结点为root的子树遍历完了,把这个结点pop,不要占用list。
(2)cousin:找到结点就return,因为路径唯一;否则找左右子,找完左右子也pop当前结点==>也就是以这个结点为root的子树遍历完了。
437. 路径总和 III ?? 非常容易出错
1 class Solution { 2 public int count = 0; // 常量类型只能提出来,和list不同,因为每次传参都不一是一个对象 3 public int pathSum(TreeNode root, int sum) { 4 if(root==null){ 5 return count; 6 } 7 findPath(root, sum); 8 pathSum(root.left, sum); 9 pathSum(root.right, sum); 10 return count; 11 } 12 public void findPath(TreeNode node, int cur){ 13 if(node==null){ 14 return; 15 } 16 if(node.val == cur){ 17 count+=1; 18 } 19 findPath(node.left, cur-node.val); 20 findPath(node.right, cur-node.val); 21 } 22 }
理解:
pathSum:以当前结点作为起始结点找路径;并且分别把左右子结点作为根,计算子树的路径。---因为题目要求起始结点不一定是root
findPath:单纯找路径。
下面是错误解法,很容易陷入重复调用:
1 class Solution { 2 public int count = 0; // 常量类型只能提出来,和list不同,因为每次传参都不一是一个对象 3 public int pathSum(TreeNode root, int sum) { 4 findPath(root, sum, sum); 5 return count; 6 } 7 public void findPath(TreeNode node, int cur, int sum){ 8 if(node==null){ 9 return; 10 } 11 if(node.val == cur){ 12 count+=1; 13 } 14 findPath(node.left, cur-node.val, sum); //(1) 15 findPath(node.right, cur-node.val, sum); 16 findPath(node.left, sum, sum); // (2) 17 findPath(node.right, sum, sum); 18 } 19
993. 二叉树的堂兄弟节点
1 class Solution { 2 public boolean isCousins(TreeNode root, int x, int y) { 3 if(root==null){ 4 return false; 5 } 6 Stack<Integer> stack1 = new Stack<>(); 7 Stack<Integer> stack2 = new Stack<>(); 8 findPath(root, x, stack1); 9 findPath(root, y, stack2); 10 stack1.pop(); 11 stack2.pop(); 12 return stack1.size()==stack2.size() && stack1.pop()!=stack2.pop(); 13 } 14 public boolean findPath(TreeNode node, int val, Stack<Integer> stack){ 15 if(node==null){ 16 return false; 17 } 18 stack.push(node.val); 19 if(node.val == val){ 20 return true; 21 }else{ 22 if(findPath(node.left, val, stack)){ 23 return true; 24 } 25 if(findPath(node.right, val, stack)){ 26 return true; 27 } 28 stack.pop(); // 注意 29 return false; 30 } 31 } 32 }
注:这道题本质就是一个查找路径问题,利用递归的思想查找路径。还有另一种解法,用两个map分别存储结点的父结点和层数,之后做对比,这种解法时间复杂度和空间复杂度都更小,因为是查一遍。但是第一种解法感觉更具普适性,保存路径的操作很多题都会用到。
1 class Solution { 2 public boolean isCousins(TreeNode root, int x, int y) { 3 if(root==null){ 4 return false; 5 } 6 Map<Integer,TreeNode> father = new HashMap<>(); 7 Map<Integer,Integer> layer = new HashMap<>(); 8 Stack<Integer> stack2 = new Stack<>(); 9 findNode(root, null, father, layer); 10 return layer.get(x)==layer.get(y) && !father.get(x).equals(father.get(y)); 11 } 12 public void findNode(TreeNode node, TreeNode par, Map<Integer,TreeNode> father, Map<Integer,Integer> layer){ 13 if(node==null){ 14 return; 15 } 16 int lay = par != null ? 1 + layer.get(par.val) : 0; 17 father.put(node.val, par); 18 layer.put(node.val, lay); 19 findNode(node.left, node, father, layer); 20 findNode(node.right, node, father, layer); 21 } 22 }
也可以把两个map定义为类成员变量,省的传来传去;father也可以用只保存val,都行。
面试题 04.08. 首个共同祖先
687. 最长同值路径
以上是关于二叉树-路径(前序)的主要内容,如果未能解决你的问题,请参考以下文章