题目
一位老师正在出一场由 n 道判断题构成的考试,每道题的答案为 true (用 ‘T’ 表示)或者 false (用 ‘F’ 表示)。老师想增加学生对自己做出答案的不确定性,方法是 最大化 有 连续相同 结果的题数。(也就是连续出现 true 或者连续出现 false)。
给你一个字符串 answerKey ,其中 answerKey[i] 是第 i 个问题的正确结果。除此以外,还给你一个整数 k ,表示你能进行以下操作的最多次数:
每次操作中,将问题的正确答案改为 ‘T’ 或者 ‘F’ (也就是将 answerKey[i] 改为 ‘T’ 或者 ‘F’ )。
请你返回在不超过 k 次操作的情况下,最大 连续 ‘T’ 或者 ‘F’ 的数目
跳转链接
做法
个人拙劣做法
首先如果序列是 TTTFFTTT , 我们可以从左到右进行搜索,如果中间存在其他不一样的字符,那么就用替换,继续让len++, 最后替换次数用完了,就 break ,进行下一次搜索。这里也是有技巧的,我们可以记录一下第一次出现不一样字符的位置p,选择p+1这个位置作为下一次搜索的起始位置。
想法比较粗糙,没有啥出彩的地方,最后一个例子还超时了
这里贴一下代码,学习一下
class Solution {
public:
int maxConsecutiveAnswers(string answerKey, int k) {
int value = max(count(answerKey,k,'F'),count(answerKey,k,'T'));
return (value <= answerKey.length() ? value : answerKey.length());
}
int count(string answerKey,int k,char c){
int maxlen = 1; //记录整个过程中的最大长度
int start = 0; //每次开始的索引
while(start<answerKey.length()){
int s = start; // 记录刚开始索引
/* 如果不是目标,那就跳过*/
if(answerKey[start] == c) {
start++;
continue;
}
int len = 1; //此循环的长度
int t = k; // 记录剩余的替换次数
/*记录下一段T的索引值*/
int first_index = 0;
bool flag = false;
//向下寻找
for(int j = start+1; j<answerKey.length();j++){
if(answerKey[j] == c) {
if(t == 0) break;
start = j;
if(!flag){
first_index = start;
flag = true;
}
--t;
}
len++;
}
maxlen = max(maxlen,len + (t>s ? s:t ));
if(flag) start = first_index;
start++;
}
return maxlen;
}
};
题解
题解用的是熟悉的滑动窗口的算法,这里讲一下滑动窗口的原理
滑动窗口
这里主要参考的是这篇文章
滑动窗口,顾名思义,就是有一个大小可变的窗口,左右两端方向一致的向前滑动(右端固定,左端滑动;左端固定,右端滑动)。 可以想象成队列,一端在push元素,另一端在pop元素
常用范围为:
- 一般是字符串或者列表
- 一般是要求最值(最大长度,最短长度等等)或者子序列
基本的算法思想是这样子的:
1.在序列中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个窗口。
2、先不断地增加 right 指针扩大窗口 [left, right],直到窗口中的序列符合要求。
3、此时,停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的序列不再符合要求。同时,每次增加 left前,都要更新一轮结果。
4、重复第 2 和第 3 步,直到 right 到达序列的尽头
思路其实很简单:第 2 步相当于在寻找一个可行解,然后第 3 步在优化这个可行解,最终找到最优解。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动。
题解代码
class Solution {
public:
int maxConsecutiveAnswers(string answerKey, int k) {
int value = max(count(answerKey,k,'F'),count(answerKey,k,'T'));
return (value <= answerKey.length() ? value : answerKey.length());
}
int count(string& answerKey,int k,char c){
int len = 1;
for(int left = 0, right = 0, sum = 0;right<answerKey.length();right++){
sum += (answerKey[right] != c);
while(sum > k){
sum -= (answerKey[left++] != c);
}
len = max(len,right-left+1);
}
return len;
}
};