LC525. 连续数组
题目:给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。
思路:①将0替换为-1 ② 算前缀和 ③ 哈希表遍历 key记录前缀和 value记录其与key相同的所有下标值 并在遍历中一直维护一个maxlength
复杂度: 时间复杂度O(n) 空间复杂度O(n)
因为刚刚做完523. 连续的子数组和,所以思路来的很快。可以两个题一起做。下面让我们举一个例子(nums=[0,0,1,0,1])。
① 涉及到连续的子数组和,我们很容易想到用前缀和来做。对于该例子的前缀和是:
nums: 0 0 1 0 1
preSum: 0 0 1 0 2
这时候我们发现,这个时候因为0这个特殊的值(多少个0相加都为0)存在,所以导致上述信息对于让0、1个数相等并没有什么帮助。
② 这个时候我们思考,反正是希望0、1二者个数相等,如果将0换为-1,抵消了也没什么关系。换完后如下:
下标: -1 0 1 2 3 4 对应的哈希表
nums: -1 -1 1 -1 1 0 -1 -2
preSum:0 -1 -2 -1 -2 -1 [-1] [0 4] [1 3]
此时我们观察preSum以及需要满足的条件如下:
i) preSum[i] == preSum[j]
ii)(j-i) %2 ==0
如 下标为0 和 2 以及 4时候都满足上述条件。如何才能满足问题中另一个限制 最长 呢?
所以在设计哈希表时候,我们的value设计为一个列表,用来记录第一次出现和最后一次出现相同值的下标。这样最后用里边两个值相减,得到的即为最大长度。得到的哈希表右上所示,最终取4(4-0>3-1).
代码
def findMaxLength(nums):
preSum, n, hs, maxlength = 0, len(nums), {0: [-1]}, 0
for i in range(n):
preSum += 1 if nums[i] else -1 # 将0替换为-1
index = hs.get(preSum, i)
if index == i: # preSum不在hs中
hs[preSum] = [index]
elif (i - index[0]) % 2 == 0:
maxlength = max(maxlength, i - index[0])
if len(index) > 1:
hs[preSum].pop()
hs[preSum].append(i)
return maxlength
路虽远,行则将至。事虽难,做则必成