目录
题目描述
给定一个二进制数组nums
和一个整数 k
,如果可以翻转最多k
个 0 ,则返回 数组中连续1
的最大个数 。
示例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。
示例2:
输入:nums = [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 <= nums.length <= 105
- nums[i] 不是 0 就是 1
- 0 <= k <= nums.length
解题思路
Collections库
介绍
Python的collections库是一个内建模块,它提供了一系列特殊的容器数据类型,用于扩展Python的标准内建容器(如字典、列表、集合和元组)。这些特殊的容器类型提供了比通用数据类型更多的选择和更好的性能,非常适合在需要高效数据处理和复杂数据结构时使用。
滑动窗口法
概念
滑动窗口是一个在序列上移动的区间,通常由左右两个指针来界定这个区间的范围。通过移动指针来改变窗口的大小和位置,在窗口移动的过程中,根据问题的需求进行特定的计算和处理。
应用场景及特点:
- 子数组 / 子串问题:
- 当需要在一个序列中找到满足特定条件的连续子数组或子串时,滑动窗口非常适用。例如,寻找和为特定值的连续子数组、含有特定字符的最长子串等。
- 窗口的大小通常是动态变化的,根据问题的条件进行调整。
- 高效性:
- 相比于暴力枚举所有可能的子数组 / 子串,滑动窗口法通常能够在更短的时间内找到解。因为它利用了子数组 / 子串的连续性和窗口的滑动特性,避免了重复计算。
- 指针移动规则:
- 通常有两个指针,一个指向窗口的左端,一个指向窗口的右端。根据问题的具体要求,以特定的方式移动指针。
- 例如,在寻找满足特定条件的最小子数组时,可能会先扩大窗口直到满足条件,然后再缩小窗口以找到最小的满足条件的窗口。
思路
这道题的核心在于找到一个最长的子数组,使得其中最多包含 k
个 0
,其余元素全为 1
。可以使用滑动窗口的技巧来解决。
- 滑动窗口:我们可以维护一个滑动窗口,该窗口内最多有
k
个0
。随着我们在数组nums
中遍历,动态调整窗口的大小和位置。 - 窗口扩展和收缩:
- 当窗口中的
0
的数量小于或等于k
时,继续扩展窗口。 - 当窗口中的
0
的数量超过k
时,收缩窗口,从窗口的左边界开始移动,直到窗口中的0
的数量再次小于或等于k
。
- 记录最大长度:在遍历的过程中,不断记录窗口的最大长度。
代码
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
max_len = left = zeros_count = 0
for right, x in enumerate(nums):
zeros_count += 1 - x
while zeros_count > k:
zeros_count -= 1 - nums[left]
left += 1
max_len = max(max_len, right - left + 1)
return max_len
复杂度分析
- 时间复杂度:
O(n)
,其中n
是数组nums
的长度。遍历数组每个元素最多一次,窗口的左边界和右边界均最多移动n
次。 - 空间复杂度:
O(1)
,只使用了常数空间来存储变量left
,right
,zeros_count
, 和max_len
。