一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
前言
每日一题,轻松解题
每日一题为刷题系列 每日刷一题LeetCode题,并且对题目进行分析,分享思路。
正文
:最大连续1的个数 III
难度:中等
题目要求:
给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
举个例子
输入:nums = [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。
:解题
方法一 :动态规划
解题思路:
我们继续观察 (1) 式,由于前缀和数组 P 是单调递增的,那么 (1) 式的右侧 P[right]−k 同样也是单调递增的。因此,我们可以发现:
随着 right 的增大,满足 (1) 式的最小的left 值是单调递增的。
这样一来,我们就可以使用滑动窗口来实时地维护left 和 right 了。在 right 向右移动的过程中,我们同步移动left,直到 left 为首个(即最小的)满足 (1) 式的位置,此时我们就可以使用此区间对答案进行更新了。
细节
当我们使用滑动窗口代替二分查找解决本题时,就不需要显式地计算并保存出前缀和数组了。我们只需要知道 left 和right 作为下标在前缀和数组中对应的值,因此我们只需要用两个变量 lsum 和 rsum 记录left 和 right 分别对应的前缀和即可。
编辑代码:
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
n = len(nums)
left = lsum = rsum = 0
ans = 0
for right in range(n):
rsum += 1 - nums[right]
while lsum < rsum - k:
lsum += 1 - nums[left]
left += 1
ans = max(ans, right - left + 1)
return ans
总结
无论做什么分析最重要,其中我们分析了题目,分析了解题思路,其实在分析完解题思路后,代码其实就是很简单的事情了,养成习惯,无论做什么之前,都要进行分析,这样有助于你更快更好的完成这件事。