最大连续1的个数 II

Submission

运行时间: 51 ms

内存: 16.4 MB

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        n = len(nums)
        res = 1
        left = 0

        i = 0
        while i < n:
            if nums[i] == 1:
                left += 1
                i += 1
            else:
                right = i + 1
                while right < n and nums[right] == 1:
                    right += 1
                if right != i + 1:
                    res = max(res, right - i + left)
                    left = right - i - 1
                    i = right
                else:
                    res = max(res, left + 1)
                    left = 0
                    i += 1

        return max(res, left)
        
        

Explain

该题解使用滑动窗口的思路来解决问题。使用两个指针 left 和 right,left 指向当前连续 1 的起始位置,right 向右扩展窗口。当遇到 0 时,计算当前窗口的长度,更新结果 res,然后将 left 移动到 right 的位置,继续向右扩展窗口。最后返回 res 和 left 中的最大值,即为最长连续 1 的长度。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        n = len(nums)
        res = 1
        left = 0

        i = 0
        while i < n:
            if nums[i] == 1:
                # 扩展左边界
                left += 1
                i += 1
            else:
                # 遇到 0,扩展右边界
                right = i + 1
                while right < n and nums[right] == 1:
                    right += 1
                if right != i + 1:
                    # 更新结果
                    res = max(res, right - i + left)
                    # 更新左边界
                    left = right - i - 1
                    i = right
                else:
                    # 更新结果
                    res = max(res, left + 1)
                    # 重置左边界
                    left = 0
                    i += 1

        # 返回结果与左边界的最大值
        return max(res, left)

Explore

题解中的逻辑`遇到0,扩展右边界`确实主要描述了在遇到0时如何处理和更新结果,这是因为0的出现可能中断连续的1序列。如果数组中没有0,该算法的循环会依然遍历整个数组,但因为没有0,i指针会连续前进,left会一直增加直到数组末尾。此时,left将记录整个数组的长度(如果全为1的话),这也会在最后通过`max(res, left)`得到正确的最大连续1的个数,即整个数组的长度。

在题解中,`left = right - i - 1`这一步骤发生在找到一个0后,right指针尝试跳过这个0并继续向前找连续的1。这一步骤的目的是为了更新left计数器,以反映在当前0之后的新一段连续1的长度。`right - i - 1`是因为right现在指向的是新段连续1的结束位置的下一个位置,减去i(当前0的位置)再减去1得到的是从i+1位置开始到right位置之前的1的数量,即新一段连续1的长度。

算法最后返回`max(res, left)`的原因在于考虑到数组末尾可能存在一段连续的1,这段连续1直到数组结束都没有被更长的序列打断。在这种情况下,left将会持续增加直到数组末尾,而如果在遍历过程中没有更新更大的res值,left可能会是最大的连续1的数量。因此,使用`max(res, left)`确保无论数组是否以1结束,都能返回正确的最大值。

在题解中,left初始化为0是因为在算法开始时,还没有遇到任何1,因此连续1的计数应从0开始。当遇到第一个1时,left会增加1,正确记录连续1的数量。如果left初始化为1,那么即使数组开头不是1,left的计数也会错误地高估。因此,初始化为0是为了精确地根据实际遇到的1的数量进行计数。