LeetCode437. 路径总和 III
【举一反三】:在二叉树中找到累加和为指定值的最长路径长度 ------ 左神P115
☆☆☆☆思路1:双重递归,第一个递归用来遍历这些节点,这二个递归用来处理这些节点,进行dfs。
思路1的缺点是存在大量重复计算,时间效率差
☆☆☆☆☆思路2:前缀和 递归回溯。 时间复杂度为O(n),空间复杂度为O(n)
代码1.1:
class Solution { // 在以root为根节点的二叉树中,寻找和为sum的路径,返回这样的路径个数 public int pathSum(TreeNode root, int sum) { if (root == null) return 0; // 每一个节点寻找的路径数 由 三部分构成 int res = findPath(root, sum); res += pathSum(root.left, sum); res += pathSum(root.right, sum); return res; } // 在以node为根节点的二叉树中,寻找包含node的路径,和为num // 返回这样的路径个数 private int findPath(TreeNode node, int num) { if (node == null) return 0; // 可以一直搜索到null int res = 0; if (node.val == num) { res += 1; // 不能直接return,因为值有负数的情况 } res += findPath(node.left, num - node.val); res += findPath(node.right, num - node.val); return res; } }
代码1.2:
class Solution { int count = 0; public int pathSum(TreeNode root, int sum) { if (root == null) return 0; dfs(root, sum); pathSum(root.left, sum); pathSum(root.right, sum); return count; } private void dfs(TreeNode node, int num) { if (node == null) return; if (node.val == num) { count ++; } dfs(node.left, num - node.val); dfs(node.right, num - node.val); } }
代码2:前缀和, 参考:前缀和,递归,回溯
class Solution { public int pathSum(TreeNode root, int sum) { // key是前缀和, value是大小为key的前缀和出现的次数 Map<Integer,Integer> map = new HashMap<>(); // 当(pathSum-sum = 0)时,说明当前路径符合要求,res + 1 map.put(0, 1); return dfs(root, map, 0, sum); } private int dfs(TreeNode root, Map<Integer,Integer> map, int curSum, int target) { // 1.递归终止条件 if (root == null) return 0; // 2.本层要做的事情 curSum += root.val; int res = 0; // currSum-target相当于找路径的起点,起点的sum+target=currSum,当前点到起点的距离就是target res += map.getOrDefault(curSum - target, 0); map.put(curSum, map.getOrDefault(curSum, 0) + 1); // 3.进入下一层 res += dfs(root.left, map, curSum, target); res += dfs(root.right, map, curSum, target); // 4.回到本层,左右子树遍历完后,恢复状态(因为这个路径不可能是别的路径的前缀了) map.put(curSum, map.get(curSum) - 1); return res; } }