930. 和相同的二元子数组

前缀和方式的代码,时间复杂度为o(n**2)
是无法通过测试用例的
def fun1(nums,goal):
    count=0
    dp=[0]  #0~n-1
    for i in nums:
        dp.append(dp[-1]+i)
    for i in range(1,len(dp)):
        for j in range(i,len(dp)):  #左闭右闭形式
            if dp[j]-dp[i-1]==goal:
                count+=1
            elif dp[j]-dp[i-1]>goal:
                break
    return count
print(fun1([1,0,1,0,1],2))
可以采取更为简单的方法,滑动窗口
不断地进入窗口,当对应的数值大于目标值时  left往右移动
当对应数值小于等于目标值时right向右移动
该滑动窗口的思路有问题,想的过于简单了
def fun2(nums,goal):
    left=0
    right=0
    count=0
    hdck=nums[left]
    while left<len(nums):
        if hdck>goal:
            left+=1
            hdck-=nums[left-1]
        else:
            if hdck==goal:
                count+=1
            if right<len(nums)-1:
                right+=1
                hdck += nums[right]
            else:
                left+=1
                hdck -= nums[left - 1]
    return count
print(fun2([1,0,1,0,1],2))


正确的思路:
(个人认为这个方法不好理解
s1,s2用来记录l1,l2到r的和(左闭右闭形式)
l1记录的是第一个sums[j]-sums[l1-1](l1到r)小于goal
l2记录的是第一个sums[j]-sums[l2-1](l2到r)等于goal
应该是因为步长为0,1的原因
这样l1-l2就是对于r所有可能的结果

def fun4(nums,goal):
    s1 = 0
    s2 = 0
    l1 = 0
    l2 = 0
    r = 0
    res = 0
    while r < len(nums):
        s1 += nums[r]
        s2 += nums[r]
        while l1 <= r and s1 >= goal:
            s1 -= nums[l1]
            l1 += 1
        while l2 <= r and s2 > goal:
            s2 -= nums[l2]
            l2 += 1
        res += l1 - l2
        r += 1
    return res

前缀和+哈希表的方法
对于一个前缀和,通过哈希表进行  sums-goal判断
这样就可以得到在  i到j区间内有多少个可行解
可以吧算法优化到o(n)

这里要注意res+=select.get(sum_-goal,0)
如果为0,则说明其自己是可以加入进去的,这就要看有几个0(自身以及其他可能为0的前缀和)
def fun3(nums,goal):
    #前缀和+哈希表
    select={}
    sum_=0
    res=0
    for i in range(len(nums)):
        #先添加
        select[sum_]=select.get(sum_,0)+1   #添加了一个0进去

        sum_+=nums[i]
        res+=select.get(sum_-goal,0)   #如果为0,则意味着刚好就是sum_ 所以要有一个 {0:1}
    return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值