空间换时间,时间换空间算法:
1 空间换时间:使用HashMap保存数据
例题1:两数之和
解法1:时间优先(HashMap)
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;++i){
int newTarget=target-nums[i];
if(map.containsKey(newTarget)){
return new int[]{
map.get(newTarget),i};
}
map.put(nums[i],i);
}
return new int[2];
}
}
解法2:空间优先(遍历所有情况)
时间复杂度:O(n^2)
空间复杂度:O(1)
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i=0;i<nums.length;++i){
for(int j=i+1;j<nums.length;++j){
int sum=nums[i]+nums[j];
if(sum==target){
return new int[]{
i,j};
}
}
}
return new int[2];
}
}
不能先排序,再左右指针。这样排序的时候,原数据的下标数据就没了
例题2:和为 K 的子数组
HashMap保存前缀和,以及其出现次数
class Solution {
public int subarraySum(int[] nums, int k) {
int result=0;
Map<Integer,Integer> map=new HashMap<Integer,Integer>();
int sum=0;
map.put(0, 1);
for(int i=0;i<nums.length;++i){
sum+=nums[i];
int need=sum-k;
if(map.containsKey(need)){
result+=map.get(need);
}
map.put(sum,map.getOrDefault(sum,0)+1);
}
return result;
}
}
例题3:路径总和 III
例题2的二叉树版本:
主要学习的题解:https://leetcode-cn.com/problems/path-sum-iii/solution/dui-qian-zhui-he-jie-fa-de-yi-dian-jie-s-dey6/
1 前缀和:一个节点的前缀和就是该节点到根之间的路径和
2 HashMap的key是前缀和, value是该前缀和的节点数量,记录数量是因为有出现复数路径的可能
3 本质还是空间换时间,保存各种前缀和出现的次数。
即:要寻找的前缀和=根节点到当前节点的路径和-targetSum
/**
* 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 {
int wholeTargetSum;
Map<Integer,Integer> map;
public int pathSum(TreeNode root, int targetSum) {
wholeTargetSum=targetSum;
map=new HashMap<>();
map.put(0,1); //十分重要的一行,不然就不能从根节点开始算了
return dfs(root,0);
}
public int dfs(TreeNode root,int pre){
if(root==null){
return 0;
}
int pathSum=pre+root.val; //获取节点到当前节点root的路径和pathSum
int needPrefix=pathSum-wholeTargetSum; //得到需要的前缀和needPrefix
int count=map.getOrDefault(needPrefix,0); //得到needPrefix对应次数
/*添加该前缀和到map中,给子节点使用
这行代码不能放在 int count=map.getOrDefault(needPrefix,0); 之前,因为路径不能不包括任何节点
*/
map