leetcode5-15每日一题:和为K的子数组

这次的题目如图所示:


题目

这道题一看我的第一反应就是存储加和结果来计数,然后根据题目下方给的提示,我创建了一个二维表来存储加和结果。
提示为:

sum(i,j)=sum(0,j)-sum(0,i), where sum(i,j) represents the sum of all the elements from index i to j-1. Can we use this property to optimize it.
sum(0,j)表示的就是nums前j和数字之和,sums(i,j)就是nums中从第i+1个数字之和到第j个数字之和。

利用这个性质,我创建了一个二维表来进行尝试:

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        lens = len(nums)
        store = [[0.5 for i in range(lens)] for j in range(lens+1)]
        store[0][0] = nums[0]
        for i in range(1,lens):
            store[0][i] = store[0][i-1] + nums[i]
        for i in range(lens):
            for j in range(i+1,lens):
                store[i+1][j] = store[0][j] - store[0][i]
        print(store)
        return sum([store[i].count(k) for i in range(lens)])

但是这种方法在面对最后那个超长的测试用例时超时了,这个我也是有预计的,因为leetcode总是会有一些十分极端的测试案例出现。
还有一个类似的方法,就是不构建数组存储结果,直接对等于k的结果计数,但是也超时了。

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        lens = len(nums)
        store = [0 for i in range(lens)]
        count = 0
        for i in range(lens):
            store[i] = store[i-1] + nums[i]
            if store[i] == k:
                count += 1
        for i in range(lens):
            for j in range(i+1,lens):
                if store[j] - store[i] == k:
                    count += 1
        return count

但是除了这个方法以外,我也没有想到有什么特别好的方法了,因为我觉得需要考虑到所有可能的加和结果,可能还是需要一个遍历的过程。于是我就直奔评论区。
先说一点,我在评论区见到了直接用我这种方法的答案,但是人家用的是C++,跟我的python还是有本质上的速度区别,难顶。
而评论区里面提到最多的方法就是使用哈希表来计数,那最方便的方法就是用字典来实现了。
参考评论区大佬们的解答,我也用python自己写了一下:

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        #通过字典来存储内容
        sums = 0
        result = 0
        #count这个表是用来存储满足条件(加和=k)的和的计数情况的
        count = {}
        count[0] = 1
        for i in range(len(nums)):
            sums += nums[i]
            #这里在判断这个key是否在计数字典中
            #如果此前sums - k被记过数,那说明sums-k的值就是其中一段从0开始的连续数组的和
            #那么说明中间有一段连续数组的加和结果是k,那就可以把这段数字的加和计数加上去
            if sums - k in count:
                result += count[sums - k]
            if sums not in count:
                count[sums] = 0
            count[sums] += 1
        return result

其中有一个遍历,其中sums用来记录每一步遍历的前i个元素的加和结果,result用来对记录符合k的项目计数,count用来对sums的出现次数计数。
result加上的计数项是从count里面来的,代码里之所以用sums-k来计数,是因为如果sums-k在count中的话,说明有某一段或多段前i项和是在在count中的,那就说明从那一段结尾的下一个元素开始到现在sums计数的结尾,这一段连续数组的和是k(也有可能是多段)。这样在单个遍历过程中就把所有加过考虑到了(因为每一个和的结果都会被记录在count中)。count[0]=1的目的是把sums=k的给加进去。
用这种方法,速度就快好多好多了,提交记录结果如下所示:


用字典的提交结果

写完后我有两个想法,一个遇到类似的计数或者加和的问题是要多用dict或者set这样的哈希表来解决问题,二是还真得捡起C++来用用,毕竟python速度还是慢了有点多(ˉ▽ˉ;)...

你可能感兴趣的:(leetcode5-15每日一题:和为K的子数组)