leetcode前缀和A系列,leetcode 1 两数之和 560和为k的子数组的个数 325和等于k的最长子数组长度 1658 将x 减到0的最小操作数 209长度最小的子数组

关于前缀和概念的介绍,可以看这篇文章
基本的思想就是对于一个长度为n的数组nums,如果我们要求其中下标l到r之间的元素的总和。
用前缀和的思想就是,先记录s[1],s[2]…s[n]的值,然后在求l到r之间元素和的时候,用s[r]-s[l-1]即可。
下面进入leetcode实战
题目有
LC 1 两数之和
LC 560 和为k的子数组的个数
LC 325 和等于k的最长子数组长度
LC 1658 将x 减到0的最小操作数
LC 209长度最小的子数组
leetcode 1 两数之和

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        d={} # key=nums[i] value=i
        for i in range(len(nums)):
            if target-nums[i] in d:
                return [d[target-nums[i]],i]
            else:
                d[nums[i]]=i

leetcode 560 和为k的子数组 的个数
这里是典型的前缀和题目

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        curr_sum = 0
        res = 0
        count = {}
        for num in nums:
            curr_sum += num
            if curr_sum == k: 
            #这里表示s[:i]全部和==k
                res += 1
            if curr_sum - k in count:
            #这里表示只有s[j:i]一部分等于k,
            #这种情况和上一种是互相独立的,并不是else
                res += count[curr_sum - k]
            count[curr_sum] = count.get(curr_sum, 0) + 1
            #这里包含两种情况,curr_sum之前存在于count中和不存在于count中
            #用上面这一句话表达了
        return res

leetcode 325 和等于 k 的最长子数组长度
给定一个数组 nums 和一个目标值 k,找到和等于 k 的最长连续子数组长度。如果不存在任意一个符合要求的子数组,则返回 0。

输入: nums = [1,-1,5,-2,3], k = 3
输出: 4
解释: 子数组 [1, -1, 5, -2] 和等于 3,且长度最长。

class Solution:
    def maxSubArrayLen(self, nums: List[int], k: int) -> int:
        # 这题跟leetcode 560类似 只是dict中的value不一样 
        # leetcode 560记录个数,这里记录index
        n=len(nums)
        res,curr_sum=0,0
        length_dict={} #key=curr_sum value=length
        for i in range(n):
            curr_sum+=nums[i]
            # print(res, length_dict)
            if curr_sum==k:
                res=i+1
            if curr_sum not in length_dict:
                length_dict[curr_sum]=i #需要把最左边的记录下来,以便下面代码的最大的记下来
            if curr_sum-k in length_dict:
                res=max(res,i-length_dict[curr_sum-k])   

        return res

leetcode 1658 将 x 减到 0 的最小操作数
给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

class Solution:
    def minOperations(self, nums: List[int], x: int) -> int:
        # 假设数组和是s 那么这里就是要求一个和为s-x的最长连续子数组 
        # 而 n-最长数组长度 就是最小操作次数
        # 参考leetcode 325
        s=sum(nums)
        n=len(nums)
        target=s-x
        idx_dict={}
        curr_sum=0
        res=float('-inf')
        for i in range(n):
            curr_sum+=nums[i]
            if curr_sum==target:
                res=i+1
            if curr_sum not in idx_dict:
                idx_dict[curr_sum]=i+1 
            if curr_sum-target in idx_dict:
                res=max(res,i+1-idx_dict[curr_sum-target])
        # print(res, idx_dict)
        if res==float('-inf'):
            return -1
        return n-res 

leetcode 209长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # 这里是>=target 用两数之和那种前缀和+哈希方法了 需要额外加一层循环 复杂度n^2
        # 用left+right 双指针 可以达到left和right同时遍历走完 不需要内嵌
        n=len(nums)
        curr_sum=0
        left,right=0,0
        res=n+1
        while right<n:
            while curr_sum<target and right<n:
                curr_sum+=nums[right]
                right+=1
            while curr_sum>=target and left<right:
                res=min(res,right-left)
                curr_sum-=nums[left]
                left+=1
        return res if res!=n+1 else 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值