class Solution { public int subarraySum(int[] nums, int k) { /** 前缀和+hash表 对于一维问题(一位区间求两个数之和是否==t),我们求出前缀和si 转换为si - sj = t,用哈希表存放si出现的次数,同时对于si,累加出哈希表中key=si-t的value(次数) 因此扫描一遍时间复杂度o(n) */ int n = nums.length; int[] s = new int[n + 1]; int res = 0; HashMap<Integer, Integer> map = new HashMap<>(); // 前缀和本身就是k map.put(0, 1); for (int i = 1; i <= n; i ++){ s[i] = nums[i - 1] + s[i - 1]; if (map.containsKey(s[i] - k)) res += map.get(s[i] - k); map.put(s[i], map.getOrDefault(s[i], 0) + 1); } return res; }}
(二维路径求和:hash+dfs+前缀和)路径总和 III
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */class Solution { HashMap<Integer, Integer> map = new HashMap<>(); int res = 0, t; public int pathSum(TreeNode root, int targetSum) { /** 对于一维问题(一位区间求两个数之和是否==t),我们求出前缀和si 转换为si - sj = t,用哈希表存放si出现的次数,同时对于si,累加出哈希表中key=si-t的value(次数) 因此扫描一遍时间复杂度o(n) 对于二维树,在dfs过程中,对于每一个点,我们要求当前点为根节点的路径中是否又满足题目要求的点 这条路径就是一维问题,因此dfs中,我们存入每个点的前缀和出现的次数,同时对于节点i,我们只需要找出key = si - t的value(次数) 回溯的过程中再把当前点的前缀和从哈希表中删掉,更新前缀和,因为当前点不算在路径里面了。 */ // 哨兵节点,表示一个数都没有的前缀和,用于dfs过程中当前点就是t map.put(0, 1); this.t = targetSum; dfs(root, 0); return res; } public void dfs(TreeNode root, int pfSum){ if (root == null) return ; pfSum += root.val; // 先加再存,防止出现t == 0,重复计算的情况 res += map.getOrDefault(pfSum - t, 0); map.put(pfSum, map.getOrDefault(pfSum, 0) + 1); dfs(root.left, pfSum);dfs(root.right, pfSum); // 回溯 map.put(pfSum, map.getOrDefault(pfSum, 0) - 1); }}