题解-今日头条2018校招后端方向(第四批)
2018-02-06 11:23
363 查看
原题链接
链接:https://www.nowcoder.net/questionTerminal/fcd645af2750401588d9e92aea05d630
有一个仅包含’a’和’b’两种字符的字符串s,长度为n,每次操作可以把一个字符做一次转换(把一个’a’设置为’b’,或者把一个’b’置成’a’);但是操作的次数有上限m,问在有限的操作数范围内,能够得到最大连续的相同字符的子串的长度是多少。
[b]输入描述:[/b]
———————————— 分界线————————————————
分析:
该字符串非 a 即 b 也就是说在区间 l~r之间把所有字符变为 a 所需的步骤数是 该区间内 b 的数量。反之亦然.
用数组 count[i] 表示 字符串中位置区间 0~i 包含的 a 的个数
则 区间 l~r 的 a 的个数为 count[r]-count[l-1]
b 的个数用 a 的个数算出 即 区间 l~r 的 b 的个数为 r+1-count[r]-(l+1-1-count[l-1])=r+1-count[r]-l+count[l-1]
在区间 l~r 的 a 和 b 的个数已知的情况下
若 区间长度step内的 a 的个数 <= m 则 可以通过 m 个步骤 产生 长度为step的字符串 b
若 区间长度step内的 b 的个数 <= m 则 可以通过 m 个步骤 产生 长度为step的字符串 a
归纳为 :若 区间长度step内的 b 或 a 的个数 <= m 则 可以通过 m 个步骤 产生 长度为step的字符串
这样 就可以直接计算出一个字符串长度(区间长度step)是否可行,因此不需要进行递推,可以直接进行二分搜索,得到最大长度。
检查一个长度step是否可行的时间复杂度为O(n),二分搜索的时间复杂度为O(log n)。
因此,该方法总的时间复杂度为 O(n*log n)
代码:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int count[50005];
int n,m;
int ans=0;
//检查当前区间长度(step)是否能在 m 个步骤内实现全 a 或 全 b
bool func(int step){
for(int i=0;i+step<n;i++){
if(m>=step+1-(count[i+step]-count[i-1]))return true; //检查 a 公式 m>=区间内 b 的个数
if(m>=count[i+step]-count[i-1])return true; //检查 b 公式: m>=区间内 a 的个数
}
return false;
}
int main(){
cin>>n>>m;
string str;
cin>>str;
//输入并计算出 count 数组
int sum=0;
for(int i=0;i<str.size();i++){
if(str[i]=='a')count[i]=++sum;
else count[i]=sum;
}
//二分搜索最大区间值
int l=0,r=n-1,mid;
while(l<r){
mid=l+(r-l)/2;
if(func(mid)){
l=mid+1;
}else r=mid;
}
ans=max(ans,l);
cout<<ans<<endl;
return 0;
}
链接:https://www.nowcoder.net/questionTerminal/fcd645af2750401588d9e92aea05d630
有一个仅包含’a’和’b’两种字符的字符串s,长度为n,每次操作可以把一个字符做一次转换(把一个’a’设置为’b’,或者把一个’b’置成’a’);但是操作的次数有上限m,问在有限的操作数范围内,能够得到最大连续的相同字符的子串的长度是多少。
[b]输入描述:[/b]
第一行两个整数 n , m (1<=m<=n<=50000),第二行为长度为n且只包含’a’和’b’的字符串s。[b]输出描述:[/b]
输出在操作次数不超过 m 的情况下,能够得到的 最大连续 全’a’子串或全’b’子串的长度。示例:
输入
8 1 aabaabaa
输出
5
说明
把第一个 'b' 或者第二个 'b' 置成 'a',可得到长度为 5 的全 'a' 子串。
———————————— 分界线————————————————
分析:
该字符串非 a 即 b 也就是说在区间 l~r之间把所有字符变为 a 所需的步骤数是 该区间内 b 的数量。反之亦然.
用数组 count[i] 表示 字符串中位置区间 0~i 包含的 a 的个数
则 区间 l~r 的 a 的个数为 count[r]-count[l-1]
b 的个数用 a 的个数算出 即 区间 l~r 的 b 的个数为 r+1-count[r]-(l+1-1-count[l-1])=r+1-count[r]-l+count[l-1]
在区间 l~r 的 a 和 b 的个数已知的情况下
若 区间长度step内的 a 的个数 <= m 则 可以通过 m 个步骤 产生 长度为step的字符串 b
若 区间长度step内的 b 的个数 <= m 则 可以通过 m 个步骤 产生 长度为step的字符串 a
归纳为 :若 区间长度step内的 b 或 a 的个数 <= m 则 可以通过 m 个步骤 产生 长度为step的字符串
这样 就可以直接计算出一个字符串长度(区间长度step)是否可行,因此不需要进行递推,可以直接进行二分搜索,得到最大长度。
检查一个长度step是否可行的时间复杂度为O(n),二分搜索的时间复杂度为O(log n)。
因此,该方法总的时间复杂度为 O(n*log n)
代码:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int count[50005];
int n,m;
int ans=0;
//检查当前区间长度(step)是否能在 m 个步骤内实现全 a 或 全 b
bool func(int step){
for(int i=0;i+step<n;i++){
if(m>=step+1-(count[i+step]-count[i-1]))return true; //检查 a 公式 m>=区间内 b 的个数
if(m>=count[i+step]-count[i-1])return true; //检查 b 公式: m>=区间内 a 的个数
}
return false;
}
int main(){
cin>>n>>m;
string str;
cin>>str;
//输入并计算出 count 数组
int sum=0;
for(int i=0;i<str.size();i++){
if(str[i]=='a')count[i]=++sum;
else count[i]=sum;
}
//二分搜索最大区间值
int l=0,r=n-1,mid;
while(l<r){
mid=l+(r-l)/2;
if(func(mid)){
l=mid+1;
}else r=mid;
}
ans=max(ans,l);
cout<<ans<<endl;
return 0;
}
相关文章推荐
- 今日头条2018校招后端方向(第二批)
- 题解-今日头条2018校招后端方向(第二批)
- 牛客网--今日头条2018校招算法方向(第一批)编程题1、编程题2
- 今日头条2018校招测试开发方向(第一、二、三、四批)编程题汇总 - 题解
- 今日头条2018校招算法方向(第一批)编程题1(离散+树状数组)
- 今日头条2018校招算法方向(第一批)编程题2(枚举)
- 手串(暴力) - 今日头条2018校园招聘后端方向(9.10)
- 今日头条2018校园招聘后端开发工程师(第四批)编程题 - 题解
- 今日头条2018校园招聘后端开发工程师(第二批)编程题 - 题解
- 今日头条2018春招-算法方向题解
- 今日头条2018校招笔试题之字符串的问题
- String Shifting- 今日头条校招2016-09-28在线编程题
- 今日头条2018实习生在线编程笔试题
- 今日头条2018春季校园招聘研发岗位笔试编程题2
- 今日头条2017后端工程师实习生笔试题
- 今日头条2018春招研发岗笔试题目
- 2018春招-今日头条笔试题-第三题(python)
- 今日头条2017后端工程师笔试题
- 校招提前批之今日头条一面
- 今日头条2018春季校园招聘研发岗位笔试编程题4