[LeetCode] #1004. Max Consecutive Ones III(最大连续1的个数 C++&Python)

本篇博客介绍了LeetCode中的1004题,即如何找到给定数组中允许改变k个0为1后的最长连续1子数组。博主提供了两种C++和Python的解决方案,详细解释了每种方法的思路,并展示了运行时间和内存使用情况。
摘要由CSDN通过智能技术生成

题目:1004. Max Consecutive Ones III

Given an array A of 0s and 1s, we may change up to K values from 0 to 1.

Return the length of the longest (contiguous) subarray that contains only 1s. 

 

Example 1:

Input: A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
Output: 6
Explanation: 
[1,1,1,0,0,1,1,1,1,1,1]
Bolded numbers were flipped from 0 to 1.  The longest subarray is underlined.

Example 2:

Input: A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
Output: 10
Explanation: 
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
Bolded numbers were flipped from 0 to 1.  The longest subarray is underlined.

Note:

  1. 1 <= A.length <= 20000
  2. 0 <= K <= A.length
  3. A[i] is 0 or 1 

题意:

给定一个包含若干整数的数列A(仅包含数字0和1),和一个整数K,求出数列A中最长连续1的个数(可以使k个0变为1,以使最长仅包含1的数列长度最长)。

分析:

最长子序列的衍生题,步骤如下:

  1. 从左往右遍历序列,同时记录最左端的位置left和最右端的位置right以及[left, right]之间包含0的个数。
  2. 如若遍历的当前位置为0, 且当前使用0 的个数小于k,那么可以就可以把当前位置记入当前子序列区间。
  3. 如果上述情况下, 当前包含0的个数大于等于k,那么及说明当前子序列区间中包含的0的个数已经达到了最大,所以需要从左往右查找子序列中包含的第一个0的位置,即将包含的第一个0之前的序列去除掉,以使[ left, right]包含0的个数不足k个。
  4. 每次将上述问题处理之后,统计当前序列的长度right-left+1 是否为当前最大,如果是,则替换即可。

第二种方法:

  1. 借助两个下标,分别指向当前位置最长连续1的左右两端。
  2. 如果 当前位置为0的时候,那么0计数器就减1。
  3. 如果0计数器小于0的时候,即可说明当前包含0的个数超量,因此 这时左端点需要跟随右端点的移动而后移。
  4. 最后只需要返回两个端点间的距离即可。

Code & C++:

auto __ =[]()
{
    std::ios::sync_with_stdio(false);
    cin.tie(nullptr);
    return nullptr;
}();
class Solution {
public:
    int longestOnes(vector<int>& A, int k) {
     	int left=0, right=0, zeros=0, maxN=0;
        while(right<A.size()){
            if(A[right]==0){
                zeros++;
            }
            while(zeros>k){
                if(A[left]==0){
                    --zeros;
                }
                left++;
            }
            maxN = max(maxN, right-left+1);
            right++;
        }
        return maxN;
    }
};

Result:

Runtime: 28 ms, faster than 100.00% of C++ online submissions for Max Consecutive Ones III.

Memory Usage: 13.6 MB, less than 100.00% of C++ online submissions for Max Consecutive Ones III.

同理,python实现如下

Code & Python

class Solution:
    def longestOnes(self, A: List[int], K: int) -> int:
        left, right, zeros, maxlen = 0, 0, 0, 0
        while right<len(A):
            if A[right]==0:
                zeros+=1
            while zeros>K:
                if A[left]==0:
                    zeros-=1
                left+=1
            maxlen = max(maxlen, right-left+1)
            right+=1
        return maxlen

Result:

Runtime: 220 ms, faster than 31.76% of Python3 online submissions for Max Consecutive Ones III.

Memory Usage: 13.7 MB, less than 100.00% of Python3 online submissions forMax Consecutive Ones III.

Code2 & Python

class Solution:
    def longestOnes(self, A: List[int], K: int) -> int:
        left, right = 0, 0
        while right<len(A):
            if A[right]==0:
                K-=1
            if K<0:
                if A[left]==0:
                    K+=1
                left+=1
            right+=1
        return right-left    #没有加1的原因是 while的终止条件为right==len(A),也即right本身已经是有效范围的下一位了,所以不需要加1了

Result:

Runtime: 136 ms, faster than 89.32% of Python3 online submissions for Max Consecutive Ones III.

Memory Usage: 13.8 MB, less than 100.00% of Python3 online submissions forMax Consecutive Ones III.

以上两种思路 核心其实是一样的,区别在于第一种当当前序列包含0的个数超量时,即从左端开始向右查找第一个填充0的位置,并以此位置开始统计下一个最长连续序列的长度,而第二种则是当填充0的个数超量时,并不是直接在左端找到第一个0填充点,而是让当前序列的左端随右端点的移动而移动,直至遇到数字0即可,而此时左右端点间的间距一直为所求最长序列的长度,而第一种方法则是时刻保存0填充的个数不超量,并且使用一个临时变量保存所遇到的最大值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值