Likou 1004 sliding window super detailed answer (reproduced)

  1. The maximum number of consecutive 1s III
    Given an array A consisting of several 0s and 1, we can change K values ​​from 0 to 1 at most.
    Returns the length of the longest (contiguous) sub-array containing only 1.

    Insert picture description here

Problem-solving ideas
First consider the most intuitive and simple idea of ​​this problem: enumerate each substring, verify its validity one by one, and update the maximum value.
The time complexity of this approach is O(n^3). In this data Under the scale, it will definitely time
out. The reason for the timeout is that a lot of repeated verification calculations have been done, and a lot of meaningless strings have been enumerated.
Based on our experience in the most value nature of such continuous sub-arrays, we use double pointers ( Sliding window) would be a very good idea

Double pointer solution
The focus of the double pointer solution is to maintain two pointers:
set two pointers (expressed as array subscript values), the left pointer points to the left boundary of the current substring, and the right pointer points to the right boundary of the current substring. We adopt a certain method Make the current substring between the left and right pointers meet the requirements: that is, the number of '0's is less than or equal to K.
Also: we can easily know that the longest string must appear in the string and the number of '0's is saturated (if there are more '0's) Or the largest (if K is relatively large), so we need to move the right pointer to the right as much as possible

So when the left pointer is fixed, under what circumstances can the right pointer move to the right?
The number of conversions K is left or
the next bit of the right pointer is '1'. By
moving the right pointer, you can find the longest valid string corresponding to each left pointer, and the next bit of the element pointed to by the right pointer must be '0' '
Then we can use each array element as the left pointer, enumerate the longest valid string in the above manner, and then return the result

But it's still not fast enough

The reason for not being fast enough is to do repeated calculations. When the left pointer changes, the right pointer starts to move right from the left pointer. The result of the last operation is not effectively used, resulting in a large number of unnecessary operations.
So how to avoid repeated calculations?

Our key lies in the "zero number saturation" just mentioned
: it may become the longest string, and the number of '0's in it must be saturated or the largest.
Then we can use some operation to make the left pointer move to the right After that, we can immediately get the saturated string with the number of '0' / the maximum string with the number of '0' corresponding to the new left pointer

First, let’s examine the situation when the left pointer moves one bit to the right:
First, we need to be clear about the fact: when the right pointer reaches the end of the string, there is no need for the left pointer to continue moving right, because the length of the substring will definitely decrease when the left pointer moves to the right. It is small, and the saturation property cannot be guaranteed.
That is, the condition for the left pointer to move to the right is: the right pointer does not touch the right boundary of the string,
then we will get an inference: when the left pointer needs to move to the right, the '0' in the string must be It is saturated rather than the largest ("saturated" means that the number of 0s in the substring is equal to K and cannot be converted from 0 to 1; "maximum" means that all 0s in the entire string have been converted to 1) both saturated and The biggest case does not need to move right

With this inference, we can consider the situation when the left pointer moves to the right:

When the element pointed to by the left pointer is '0': when the left pointer moves to the right, the number of '0' in the substring is reduced by one. In order to maintain its saturation property, we just mentioned that "the next bit of the element pointed to by the right pointer must be It is '0'", so the right pointer must be moved right by at least one bit (if the next bit after the right movement is '1', then you can continue to move right)
when the element pointed to by the left pointer is '1': when the left pointer When shifting to the right, the number of '0's in the substring remains unchanged. Because we maintain the saturation properties of each substring, the right pointer cannot be
moved right. After a series of operations of each left pointer movement and subsequent right pointer movement, it is updated. Maximum value
Through the above operations, traverse until the right pointer touches the right boundary of the array, and you can get the global maximum length of the qualified string

Author: amachi-inori
link: https: //leetcode-cn.com/problems/max-consecutive-ones-iii/solution/c-1004-hua-dong-chuang-kou-chao-xiang-xi-jie-shuo -/
Source: LeetCode
Insert picture description here

//天知いのり 2020.5.24
class Solution {
    
    
public:
    int longestOnes(vector<int>& A, int K) {
    
    
        int left(0), right(0);
        int max(0);
        while (left <= right && right < A.size()) {
    
    
            while (right < A.size() && (A[right] || K != 0)) {
    
    
                if (!A[right]) K--;
                right++;
            }
            max = std::max(right - left, max);
            if (A[left]) left++;
            else left++, right++;
        }
        return max;
    }
};

作者:amachi-inori
链接:https://leetcode-cn.com/problems/max-consecutive-ones-iii/solution/c-1004-hua-dong-chuang-kou-chao-xiang-xi-jie-shuo-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

my solution

class Solution {
    
    
public:
	int longestOnes(vector<int>& A, int K) {
    
    
		int len = A.size();
		int left = 0, right = 0;//窗体起始点&最终点下一个位置
		int max_lenth = 0;
		int cur_lenth = 0;
		int nums = 0;//记录0的个数
		while (left <= right && right < len) {
    
    
			while (right < len &&(nums < K || A[right]) ) {
    
    //当窗体内0的个数小于K的时候就扩增窗体
				if (A[right] == 0)
					nums++;
				right++;
			}
			//出循环之后此时窗体内0的数目为K
			cur_lenth = right - left;//当前窗口的大小
			if (cur_lenth > max_lenth)
				max_lenth = cur_lenth;
			if (!A[left])
				left++, right++;//当窗口最左端为0,右移之后又可以继续向左扩大窗口
			else
				left++;//若最左边是1,那么移动之后会少一个1,右侧暂且不动
		}
		return max_lenth;
	}
};

Guess you like

Origin blog.csdn.net/Genius_bin/article/details/113446625