一. 问题描述
小R得到了一个由大写字母组成的字符串,长度为 n。她可以对字符串中的字符进行修改,每次操作允许将某个位置的字符修改为任意字符。例如,字符串 ABC 的第一个字符 A 改为 B,则字符串变为 BBC。她最多可以进行 k 次这样的修改。
小R想知道,通过最多 k 次修改后,字符串中由最多两种不同字母组成的最长连续子串的长度是多少。
测试样例
样例1:
输入:
n = 6 ,k = 1 ,inp = "ABCBAD"
输出:5
样例2:
输入:
n = 5 ,k = 1 ,inp = "AEABD"
输出:4
样例3:
输入:
n = 8 ,k = 2 ,inp = "AAAABBCD"
输出:8
题目链接:www.marscode.cn/practice/36…
二. 思路解析
2.1 问题理解
我们需要找到一个由最多两种不同字母组成的最长连续子串,并且可以通过最多 k 次修改来实现。这里的修改是指将某个位置的字符修改为任意字符。
2.2 数据结构选择
由于我们需要处理字符串,并且需要频繁地访问和修改字符串中的字符,因此选择字符串作为主要的数据结构是合适的。
三. 解题步骤
3.1 算法步骤
- 双层循环:我们需要尝试将字符串中的每个字符作为目标字符之一。由于字符串只包含大写字母,因此我们可以使用两个嵌套的循环来遍历所有可能的目标字符对(
target1和target2)。 - 滑动窗口:使用滑动窗口技术来找到满足条件的最长子串。滑动窗口由两个指针
left和right组成,表示当前窗口的左右边界。 - 修改次数管理:在滑动窗口的过程中,我们需要记录当前窗口内需要修改的字符数
changes。如果changes超过k,则需要移动left指针,直到changes小于等于k。 - 更新最大长度:在每次移动
right指针时,更新最大长度maxLength。
3.2 具体步骤
-
初始化:初始化
maxLength为 0。 -
双层循环:外层循环遍历所有可能的目标字符
target1,内层循环遍历所有可能的目标字符target2。 -
滑动窗口:
-
初始化
left和right指针为 0。 -
初始化
changes为 0。 -
当
right指针小于n时,执行以下操作:- 如果当前字符
inp.charAt(right)既不是target1也不是target2,则changes加 1。 - 如果
changes超过k,则移动left指针,直到changes小于等于k。 - 更新
maxLength为当前窗口长度right - left + 1和maxLength中的较大值。 - 移动
right指针。
- 如果当前字符
-
-
返回结果:返回
maxLength。
3.3 复杂度分析
3.3.1 时间复杂度分析
-
双层循环:
- 外层循环遍历所有可能的目标字符
target1,从'A'到'Z',共 26 次。 - 内层循环遍历所有可能的目标字符
target2,从'A'到'Z',共 26 次。 - 因此,双层循环的总次数为
26 * 26 = 676次。
- 外层循环遍历所有可能的目标字符
-
滑动窗口:
- 在每次双层循环中,滑动窗口的
right指针会遍历整个字符串inp,长度为n。 - 在每次滑动窗口的过程中,
left指针最多移动n次。 - 因此,滑动窗口的总操作次数为
O(n)。
- 在每次双层循环中,滑动窗口的
综合以上分析,双层循环和滑动窗口的总时间复杂度为 O(26^2 * n),即 O(676 * n)。由于 676 是一个常数,因此实际的时间复杂度为 O(n)。
3.3.2 空间复杂度分析
-
变量存储:
- 代码中使用了几个变量来存储指针、计数器和最大长度,这些变量的空间占用是常数级别的,即
O(1)。
- 代码中使用了几个变量来存储指针、计数器和最大长度,这些变量的空间占用是常数级别的,即
-
字符串:
- 输入字符串
inp的空间占用为O(n),其中n是字符串的长度。
- 输入字符串
综合以上分析,代码的空间复杂度为 O(n),主要由输入字符串的空间占用决定。
四. Code
public class Main {
public static int solution(int n, int k, String inp) {
int maxLength = 0;
// 尝试将字符串中的每个字符作为目标字符之一
for (char target1 = 'A'; target1 <= 'Z'; target1++) {
for (char target2 = 'A'; target2 <= 'Z'; target2++) {
if (target1 == target2) continue; // 跳过相同字符的情况
int left = 0, right = 0;
int changes = 0;
// 使用滑动窗口来找到最大长度
while (right < n) {
if (inp.charAt(right) != target1 && inp.charAt(right) != target2) {
changes++;
}
// 如果修改次数超过k,移动左指针
while (changes > k) {
if (inp.charAt(left) != target1 && inp.charAt(left) != target2) {
changes--;
}
left++;
}
// 更新最大长度
maxLength = Math.max(maxLength, right - left + 1);
right++;
}
}
}
return maxLength;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(6, 1, "ABCBAD") == 5);
System.out.println(solution(5, 1, "AEABD") == 4);
}
}
五.总结
通过使用AI解决编程题目,开发者可以获得以下好处:
- 提高效率:AI可以自动生成代码和测试用例,减少手动编写代码的时间。
- 优化性能:AI提供代码优化建议,帮助开发者提升代码的性能。
- 学习提升:AI提供解题思路和算法步骤的解析,帮助开发者学习新的编程技巧。