每日一题 -- LeetCode1004

283 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情image.png

前言

每日一题,轻松解题

每日一题为刷题系列 每日刷一题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

总结

无论做什么分析最重要,其中我们分析了题目,分析了解题思路,其实在分析完解题思路后,代码其实就是很简单的事情了,养成习惯,无论做什么之前,都要进行分析,这样有助于你更快更好的完成这件事。