#487 Max Consecutive Ones II (Medium)
Given a binary array
nums
, return the maximum number of consecutive1
's in the array if you can flip at most one0
.
解题思路:
因为最多可以翻转一个0,那么等同于0所包围的1可以看成可用于加法的有效片段。结果就是取邻近的两个片段之和的最大值再加1。
edge case是,整个数列没有0,或者只有1个0,那么结果直接是数列的长度。
有效片段的长度,用one_counter来统计。因为还要考虑0的长度,zero_counter,如果超过1,那么两个片段之间就不可以相加。用prev来储存上一个有效片段的长度值,用于和当前的one_counter相加,相加之和与之前邻近片段之和作对比,取最大值。
直到数列的最后一个数值。如果最后一个数值为1,那么当前的one_counter还没有参与到相加的运算中,所以要补一步。如果最后一个数值为0,那么已经当前的one_counter已经参与了,没有浪费。
(步骤有点繁琐,可能问题拆解还不是最优解。要参考一下其他solution)
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
if 0 not in nums or nums.count(0) == 1:
return len(nums)
one_counter = zero_counter = prev = addition = 0
for i in nums:
if i == 1:
one_counter += 1
zero_counter = 0
else:
zero_counter += 1
if zero_counter > 1:
prev = 0
if one_counter != 0:
addition = max(addition, prev + one_counter)
prev, one_counter = one_counter, 0
if one_counter != 0:
addition = max(addition, prev + one_counter)
return addition+1
runtime:
Discussion Forum里cmc也是这个思路,分为prev和curr。但是没有那么复杂。暂时还没看懂,怎么处理很多个0间隔的,以及整个数列只有1个0或没有0的情况。
class Solution(object):
def findMaxConsecutiveOnes(self, nums):
# previous and current length of consecutive 1
pre, curr, maxlen = -1, 0, 0
for n in nums:
if n == 0:
pre, curr = curr, 0
else:
curr += 1
maxlen = max(maxlen, pre + 1 + curr )
return maxlen
绝了。总算看懂。通过把pre设为-1,来解决数列中没有0或者只有1个0的情况。确实也make sense。如果一直没有遇到零,那么就不存在prev,上一个有效片段。如果只存在1个0,那么当下的有效片段,curr就是0,如果遇到第二个0,就通过把curr的0值给到prev,来清空prev的值。所以其实没有必要统计0的个数。通过当前输入的数为0,来控制prev和curr的应有值。
还有个和之前思路的最大的不同,是把提取两者之和的最大值放在了遇到1的时候做,我之前是遇到0的时候才做。所以放在遇到1的时候执行,就不必在区分最后一个数为0还是1,不存在漏掉curr的情况。也就没有重复max()这个语句。
再重写一遍:
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
prev, counter, longest = -1, 0, 0
for i in nums:
if i == 0:
prev, counter = counter, 0
else:
counter += 1
longest = max(longest, prev + counter + 1)
return longest
(倒着推能看懂,但是不看的话,真的很难自己总结出这样的思路……还是水平没到
runtime:
一定要二刷和多看的题。