y总代码总结
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 300010;
int n, m; //这里用 m 表示题目中的 k (习惯原因)
int w[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%d", &w[i]); //读入棋盘。
int len = 0, r = 0; // len 为最大长度,r 为右指针的位置。
for (int i = 0, j = 0, zeros = 0; i < n; i ++ )
{ //构造滑动窗口型双指针 i 和 j ,其中 i 为右指针,j为左指针,zeros 为判断指标。
if (!w[i]) zeros ++ ; //如果 i 指向的元素为 0 ,zeros后自增。
while (zeros > m) //当 0 的数量大于 m 的数量时(窗口长度达到界限):
{
if (!w[j]) zeros -- ; //若此时 j 指向的元素为 0 ,则 zeros 后自减。
j ++ ; // j 后自增(以保证窗口长度不变)。
}
int t = i - j + 1; // t 为当前窗口长度。
if (t > len) len = t, r = i; //若 t 的长度大于先前的最大长度,则更新 len 和 r。
}
printf("%d\n", len);
for (int i = r; i > r - len; i -- ) w[i] = 1; //从右指针 i 的位置向左遍历 len 个长度并赋为 1。
for (int i = 0; i < n; i ++ ) printf("%d ", w[i]); //输出棋盘。
return 0;
}
个人复盘
为什么没做出来?问题出在哪里?你该怎么解决问题?
思路错误。想到可能用滑动窗口,但由于基础不牢固,没办法实现,于是想改用其他算法,最后没做出来。
题目本身并不算难,难度中等偏下、简单偏上。问题出在做题量和代码的熟练度,需要加强复习。
多刷题多coding,总结双指针算法模型。
复盘后写的代码(和y总的基本一致)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 300010;
int main(){
int n, k, a[N];
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i ++ ){
scanf("%d", &a[i]); //读入棋盘(0 ~ n-1)。
}
int max, rp; //max 为题中求的最大长度,rp 为右指针的位置。
for(int l = 0, r = 0, zr = 0; r < n; r ++ ){
//构造双指针滑动窗口模型,l 为左指针,r 为右指针,zr 为判断指标。
if(!a[r]) zr ++ ; //若右指针 r 指向的元素为 0,则 zr 后自增。
while(zr > k){ //当窗口达到长度界限时:
if(!a[l]) zr -- ; //若左指针 l 指向的元素为 0,则 zr 后自减。
l ++ ; //左指针 l 右移。
}
int len = r - l + 1; //len 为当前的窗口长度(由于 l 和 r 是下标索引,实际长度要加一)。
if(len > max){ //若当前的窗口长度大于先前的最大长度,则更新 max 和 rp。
max = len;
rp = r;
}
}
printf("%d\n", max);
for(int j = rp; j > rp - max; j -- ){
a[j] = 1; //根据 max 对应的棋盘长度和位置更新棋盘。
}
for(int k = 0; k < n; k ++ ){
printf("%d ", a[k]); //输出棋盘。
}
return 0;
}