1004. 最大连续1的个数 III
给定一个由若干 0
和 1
组成的数组 A
,我们最多可以将 K
个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。
示例 1:
输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2 输出:6 解释: [1,1,1,0,0,1,1,1,1,1,1] 粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3 输出:10 解释: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] 粗体数字从 0 翻转到 1,最长的子数组长度为 10。
提示:
1 <= A.length <= 20000
0 <= K <= A.length
A[i]
为0
或1
Solution One:
sliding window
在curZero<=K的条件下往右expand,当curZero>K的时候从左边shrink
值得一提的是当r指针到数组末尾的时候,如果数组末尾值是1,curOne就会少算1,所以采用A.append(1)的方法处理这种情况,同时也不会影响r指针在指到末尾之前就已经取得maxWindow的情况
class Solution: def longestOnes(self, A: List[int], K: int) -> int: if len(A)-sum(A)<=K:return len(A) l=r=maxWindow=curWindow=curZero=curOne=0 A.append(1) while r<len(A): while curZero<=K and r<len(A): curWindow=curOne+curZero maxWindow=max(maxWindow,curWindow) if A[r]==0: curZero+=1 else: curOne+=1 r+=1 while curZero>K: if A[l]==0: curZero-=1 else: curOne-=1 l+=1 return maxWindow
这是比较直观的容易想到的解法,再来
Solution Two:
首先数1,如[1,1,1,0,0,0,1,1,1,0]计数变为[3,4],再加上一个数组[3]表示3,4中间有3个0,即只需将这3个0改为1,即可完成2个部分的拼接,然后:
1贪心:一定要把连续的0换成1,这样连起来的才是最长的。
2基本上转化为two pointer problem,找到一个滑动窗口,里面0的个数不超过K,1也是最多的
class Solution: def longestOnes(self, A: List[int], K: int) -> int: if len(A)-sum(A)<=K:return len(A) if sum(A)==0:return K profit=[] cost=[] i=0 while i<len(A) and A[i]==0:i+=1 while i<len(A): j = i while j<len(A) and A[j]==1: j+=1 profit.append(j-i) k = j while k<len(A) and A[k]==0: k+=1 cost.append(k-j) i = k cost.pop() res = K+max(profit) i = j = used = 0 contig = profit[0] while j<len(cost): while j<len(cost) and K-used>=cost[j]: used+=cost[j] contig += profit[j+1] j+=1 if i==j: i+=1 j+=1 continue res=max(res,contig+K) used-=cost[i] contig-=profit[i] i+=1 return res