LeetCode 974
最开始的想法是presum,然后o(n*n)求出所有的sub array的和,直接算count。这样效果不好。
在考虑要求最大能by K整除的连续子数组个数,如果我们知道到前面这些可能的remainder,那么加上自己,最后如果能by K整除,那么就是一个结果。我们可以用一个dictionary记住前面所有remainder的可能个数。
def subarraysDivByKT2(self, A: List[int], K: int) -> int:
if A == None: return 0
n = len(A)
dp = collections.defaultdict(int)
count = 0
for a in A:
r = a % K
if r == 0:
dp[0] += 1
count += dp[0]
else:
dp2 = collections.defaultdict(int)
for i in dp.keys():
dp2[(i+r)%K] = dp[i]
dp = dp2
dp[r] +=1
count += dp2[0]
return count
这是个o(n*n)的方法,虽然结果对,但是效率上还是不行。每次我们都需要轮换的所有到目前这个数的余数求出来。这个是个变化的值,如果进一步考虑,反过来,没0位置到所有位置上的presum是固定的,那么remainder也是固定的,如果i,j两个位置的remainder是一样的,那么【i+1,j】的子数组和应该可以被K整除。这样一来这个题目就简单了,我们只要记住所有之前的remainder,然后查个数就好了。
def subarraysDivByK(self, A: List[int], K: int) -> int:
if A == None: return 0
n = len(A)
dp = collections.defaultdict(int)
dp[0] = 1
count = 0
current = 0
for a in A:
r = a % K
current = (current + r) % K
count += dp[current]
dp[current] +=1
return count
LeetCode 525
这个题目和上面这个题目其实非常类似,记住了每个位置上少了多少0,或者多了多少1, 那么正好到现在的位置上有一样的多余的话【i+1,j】就是一个具有同样多0和1的连续字串。
def findMaxLength(self, nums: List[int]) -> int:
if nums == None: raise Exception("invalid input")
n = len(nums)
diffDic = collections.defaultdict(int)
diffDic[0] = -1
current = 0
maxl = 0
for pos in range(n):
if nums[pos] == 0: current -=1
else: current += 1
if current in diffDic:
maxl = max(maxl, pos - diffDic[current])
else:
diffDic[current] = pos
return maxl