力扣513题、112题、113题(找树左下角的值,路径总和)
513、找树左下角的值
基本思想:
树的最后一行找到最左边的值
树的最后一行:深度最大的叶子节点---前序遍历
最左边:优先左边搜索---前序遍历
具体实现:
1、确定递归参数和返回值
参数:根节点和int型变量记录深度
返回值:不需要
如果要遍历整棵树,递归函数不能有返回值
如果要遍历某一条固定路线,递归函数就一定要返回值
本题要遍历整个树找到最深的叶子节点,需要遍历整棵树,所以没有返回值
2、终止条件
遇到叶子节点,统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度maxLen。
if (root.left == null && root.right == null){ if (leftLen > maxLen) { maxLen = leftLen; maxLeftValue = root.val; } return; }
3、单层递归逻辑
回溯
前序遍历最先碰到的叶子节点一定是左叶子节点
代码:
class Solution { private int maxLen = -1; //这两个值都是用来存放结果的 private int maxLeftValue = 0; public int findBottomLeftValue(TreeNode root) { findLeftValue(root,0); return maxLeftValue; } private void findLeftValue (TreeNode root, int leftLen){//leftLen是用来记录路径的 if (root == null) return; if (root.left == null && root.right == null){ if (leftLen > maxLen) { maxLen = leftLen; maxLeftValue = root.val; } return; } if (root.left != null){ leftLen++; findLeftValue(root.left,leftLen); leftLen--; } if(root.right != null){ leftLen++; findLeftValue(root.right,leftLen); leftLen--; } return; } }
迭代法
class Solution { public int findBottomLeftValue(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); int res = 0; while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { TreeNode poll = queue.poll(); if (i == 0) { res = poll.val; } if (poll.left != null) { queue.offer(poll.left); } if (poll.right != null) { queue.offer(poll.right); } } } return res; } }
112、路径总和
基本思想:
前中后序遍历都可以
具体实现:
1、确定递归参数以及返回值
递归参数:根节点,计数器(用于计算二叉树的一条边是否正好是目标和)
返回值:搜索其中一条符合条件的路径,需要返回值
从遍历的路线看出,不需要遍历整棵树,所以递归函数需要返回值,用布尔类型
2、确定终止条件
计数器count初始化为目标和
然后每次减去遍历路径节点上的数值
如果count==0,同时到了叶子节点,说明找到了目标节点
如果到了叶子节点,count不为0,说明没找到
3、单层递归逻辑
回溯
代码:
class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) { return false; } return traversal(root, targetSum - (root.val)); } private boolean traversal(TreeNode root, int count){ if (root.left == null && root.right == null && count == 0) return true; if (root.left == null && root.right == null) return false; if (root.left != null) { count -= root.left.val; if (traversal(root.left, count)) return true; count += root.left.val; } if (root.right != null) { count -= root.right.val; if (traversal(root.right, count)) return true; count += root.right.val; } return false; } }
class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) { return false; } return traversal(root, targetSum); } public boolean traversal(TreeNode root, int count) { if (root.left == null && root.right == null && count - root.val == 0) { return true; } if (root.left == null && root.right == null) return false; if (root.left != null) { count -= root.val; if( traversal(root.left, count)) return true; count += root.val; } if (root.right != null) { count -= root.val; if( traversal(root.right, count) ) return true; count += root.val; } return false; } }
迭代法
class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) { return false; } Stack<TreeNode> stack1 = new Stack<>(); Stack<Integer> stack2 = new Stack<>(); stack1.push(root); stack2.push(root.val); while (!stack1.isEmpty()){ int size = stack1.size(); for (int i = 0; i < size; i++){ TreeNode node = stack1.pop(); int sum = stack2.pop(); // 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true if (node.left == null && node.right == null && sum == targetSum) return true; // 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来 if (node.right != null) { stack1.push(node.right); stack2.push(sum+node.right.val); } // 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来 if (node.left != null) { stack1.push(node.left); stack2.push(sum+node.left.val); } } } return false; } }
113、路径总和ii
基本思想:
具体实现:
返回值:不需要,因为要遍历整个树
代码:
class Solution { public List<List<Integer>> pathSum(TreeNode root, int targetSum) { List<List<Integer>> res = new ArrayList<>(); if (root == null) return res; List<Integer> path = new LinkedList<>(); preorderdfs(root, targetSum, res, path); return res; } public void preorderdfs(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path){ path.add(root.val); if (root.left == null && root.right == null){ if(targetSum - root.val == 0){ res.add(new ArrayList<>(path)); } return; } if (root.left != null){ preorderdfs(root.left, targetSum - root.val, res, path); path.remove(path.size() - 1); } if (root.right != null){ preorderdfs(root.right, targetSum - root.val, res, path); path.remove(path.size() - 1); } } }
class Solution { public List<List<Integer>> pathSum(TreeNode root, int targetSum) { List<List<Integer>> res = new ArrayList<>(); List<Integer> paths = new ArrayList<>(); if (root == null) return res; traversal(root, targetSum, res, paths); return res; } public void traversal(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> paths) { paths.add(root.val); if (root.left == null && root.right == null) { if (targetSum - root.val == 0) { res.add(new ArrayList<>(paths)); } return; } if (root.left != null) { targetSum -= root.val; traversal (root.left, targetSum, res, paths); paths.remove(paths.size() - 1); targetSum += root.val; } if (root.right != null) { targetSum -= root.val; traversal (root.right, targetSum, res, paths); paths.remove(paths.size() - 1); targetSum += root.val; } } }
class Solution { public List<List<Integer>> pathSum(TreeNode root, int targetSum) { List<List<Integer>> res = new ArrayList<>(); List<Integer> paths = new ArrayList<>(); if (root == null) return res; paths.add(root.val); traversal(root, targetSum - root.val, res, paths); return res; } public void traversal(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> paths) { if (root.left == null && root.right == null) { if (targetSum == 0) { res.add(new ArrayList<>(paths)); } return; } if (root.left != null) { paths.add(root.left.val); targetSum -= root.left.val; traversal (root.left, targetSum, res, paths); paths.remove(paths.size() - 1); targetSum += root.left.val; } if (root.right != null) { paths.add(root.right.val); targetSum -= root.right.val; traversal (root.right, targetSum, res, paths); paths.remove(paths.size() - 1); targetSum += root.right.val; } } }