题意:
给你一个长度为
的01数组,你可以将其中
个数字0变成数字1,问变化后数组中最长连续的一段1长度是多少?
解法一(暴力求解,不可AC)
首先我们可以枚举数组中每一个数,当枚举到第
个数时,我们可以暴力求出以第
个数为结尾,最长的连续一段1长度的值,我们记其为第
个数对答案的贡献
最终答案即为所有贡献的最大值
具体的:
对于第
个数字,我们可以暴力往前循环,若遇到0,则将
减一;若遇到1,则继续向前,直到无法向前或者
为0则结束循环
最后对于第
个数字的贡献即为遇到数字的总个数
(注意每次
要恢复为原来的值)
代码:
class Solution {
public:
int solve(int n, int m, vector<int>& a) {
int ans=0;//最终答案
for(int i=0;i<n;i++){
int t=m;//临时存储m
int c=0;//遇到的数字个数
for(int j=i;j>=0&&t>0;j--){
c++;//数字个数+1
if(a[j]==0)t--;//消耗一次变1的机会
}
ans=max(ans,c);//答案取最大值
}
return ans;
}
}; 时间复杂度: 空间复杂度:
,程序中需要存储
个整型数字和若干个整型变量,故空间复杂度为)
解法二(队列优化)
在解法一中,程序主要的时间瓶颈是对于每个数字计算贡献需要
的时间
我们同样是考虑计算以第
个数为结尾,最长的连续一段1长度的值
我们考虑解法一中往前枚举将0变成1的过程,0的位置一定是距离当前位置最近的
个0所在的位置,这
个位置我们可以用一个大小为
的队列来维护
例如下图所示的例子:
我们设
表示以第
个元素为结尾,最长的连续的1的长度,显然有:
我们设
表示若第
个数字为1,以第
个元素为结尾,最长的连续的1的长度,显然有:
我们假设队头元素为
,显然由于队列存储的是距离当前位置最近的
个0所在的位置,则
后面的0一定变成了1,则当前以第
个数为结尾,最长的连续一段1长度的值为
于是我们只需要预处理出
数组,然后在枚举每一个数字的过程中维护上述队列即可,最后答案即为最大的以第
个数为结尾,最长的连续一段1长度的值
代码:
class Solution {
public:
int f[1000000];//以第i个元素为结尾,最长的连续的1的长度
int g[1000000];//若第i个元素为1,最长的连续的1的长度
int solve(int n, int m, vector<int>& a) {
memset(f,0,sizeof f);
memset(g,0,sizeof g);//多测清空
f[0]=a[0];
g[0]=1;
for(int i=1;i<a.size();i++){
if(a[i]){
f[i]=f[i-1]+a[i];
}else{
f[i]=0;
}
g[i]=max(f[i],f[i-1]+1);
}
queue<int> que;
int ans=a[0];//表示最终答案
for(int i=1;i<n;i++){
if(!a[i]){
//若当前数字为0
if(que.size()==m)que.pop();//队列大小最大只能为m
que.push(i);
if(m>1){
ans=max(ans,i-que.front()+g[que.front()]);
}else{
//若只能改变一个0,则当前位置对答案的贡献为g[i]
ans=max(ans,g[i]);
}
}else{
if(que.size()>0){
ans=max(ans,i-que.front()+g[que.front()]);
}else{
ans=max(ans,f[i]);
}
}
}
return ans;//返回答案
}
}; 时间复杂度:空间复杂度:

京公网安备 11010502036488号