leetcode刷题 | 关于前缀和题型总结1

33 篇文章 1 订阅
29 篇文章 3 订阅

leetcode刷题 | 关于前缀和题型总结1

题目链接

560. 和为 K 的子数组 - 力扣(LeetCode)

525. 连续数组 - 力扣(LeetCode)

209. 长度最小的子数组 - 力扣(LeetCode)

437. 路径总和 III - 力扣(LeetCode)

和为K的子数组

前缀和:默认下标可以从1开始

前缀和是指某序列的前n项和,可以把它理解为数学上的数列的前n项和
在这里插入图片描述

class Solution {
    public int subarraySum(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        map.put(0,1);
        int[] sums = new int[nums.length+1];
        for(int i = 1;i<nums.length+1;i++){
            sums[i] = sums[i-1]+nums[i-1];
        }
        int res = 0;
        for(int i = 1;i<sums.length;i++){
            int target = sums[i]-k;
            res += map.getOrDefault(target,0);
            map.put(sums[i],map.getOrDefault(sums[i],0)+1);
        }
        return res;
    }
}

可以先计算出每一个元素的前缀和,本题求解的是和为k的子数组,也就是从下标[j,i]元素的和为k,这条件可以表示为sums[i]-sums[j-1] == k,,那么进行变换可以得到sums[i]-k == sums[j-1],就可以转换为前缀和sums数组中有多少个值等于sum[i]-k

map保存的是以前缀和为键,出现的次数为值,通过从map中获取到sums[j-1]的个数

每一次循环都要将得到的前缀和存入到map中,以便下一次计算

之后的每一道题的思想都类似于本题

连续数组/0 和 1 个数相同的子数组

class Solution {
    public int findMaxLength(int[] nums) {
        int res = 0;
        int[] sums = new int[nums.length+1];
        for(int i = 1;i<sums.length;i++){
            sums[i] = sums[i-1]+(nums[i-1] == 0? -1 : 1);
        }
        Map<Integer,Integer> map = new HashMap();
        map.put(0,0);
        for(int i = 1;i<sums.length;i++){
            if(map.containsKey(sums[i])) res = Math.max(res,i-map.get(sums[i]));
            else map.put(sums[i],i);
        }
        return res;
    }
}

和大于等于 target 的最短子数组/长度最小的子数组

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int start = 0;
        int sum = 0;
        int res = Integer.MAX_VALUE;
        for(int i= 0; i< nums.length;i++){
            sum+=nums[i];
            while(sum >= target){
                res = Math.min(res,i-start+1);
                sum -= nums[start];
                start ++;
            }
            
        }
        return res == Integer.MAX_VALUE?0: res;
    }
}

路经总和Ⅲ

前缀和解法

class Solution {
    public int pathSum(TreeNode root, long targetSum) {
        Map<Long, Integer> prefix = new HashMap<Long, Integer>();
        prefix.put(0L, 1);
        return dfs(root, prefix, 0, targetSum);
    }
    public int dfs(TreeNode root,Map<Long,Integer> prefix,long cur,long target){
        if (root == null) return 0;
        int res = 0;
        cur += root.val; //当前节点的前缀和
        res = prefix.getOrDefault(cur-target,0);
        prefix.put(cur,prefix.getOrDefault(cur,0)+1);
        res += dfs(root.left,prefix,cur,target);
        res += dfs(root.right,prefix,cur,target);
        //回溯
        prefix.put(cur,prefix.getOrDefault(cur,0)-1);
        return res;
    }
}

递归解法

class Solution {
   public int pathSum(TreeNode root, long targetSum) {
        if(root == null) return 0;
        int count = nodeSum(root, targetSum);
       // 每一个节点都作为根节点进行递归
        return count + pathSum(root.left, targetSum) + pathSum(root.right, targetSum);
    }
    private int nodeSum(TreeNode node, long targetSum){
        if(node == null) return 0;
        int count = 0;
        long val = node.val;
        if(val == targetSum) count++;
        return count + nodeSum(node.left, targetSum - val) + nodeSum(node.right, targetSum - val);
    }
}

targetSum) count++;
return count + nodeSum(node.left, targetSum - val) + nodeSum(node.right, targetSum - val);
}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小七rrrrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值