寻找最长神奇数列问题的双指针解法分析
一、问题理解
本题要求在一个由 0 和 1 组成的字符串序列中,找出最长的“神奇数列”。所谓“神奇数列”是指序列中至少由 3 个连续的 0 和 1 交替出现组成的部分数列。如果有多个最长的神奇数列,则输出最先出现的那一个。这就是一个双指针的基础题,思路很清晰,不断遍历,记录最大长度,相邻两字符相等时神奇序列就停止。
我们可以先询问豆包给出一些步骤提示
然后我们可以写出自己的代码
二、solution函数
public static String solution(String inp) {
int n = inp.length();
// 用于记录最长神奇数列的长度,初始化为0
int maxLength = 0;
// 用于记录最长神奇数列在原字符串中的起始索引,初始化为0
int startIndex = 0;
// 外层循环,从字符串开头开始遍历,i为可能的神奇数列起始位置
for (int i = 0; i < n; i++) {
int j = i;
// 内层循环,从当前起始位置i开始向后遍历
while (j < n) {
// 计算当前从i到j的子串长度
int length = j - i + 1;
// 如果已经到达字符串末尾或者当前字符和下一个字符相等(可能是神奇数列结束)
if (j == n - 1 || inp.charAt(j) == inp.charAt(j + 1)) {
// 检查子串长度是否大于等于3
if (length >= 3) {
// 如果当前子串长度大于已记录的最长神奇数列长度
if (length > maxLength) {
maxLength = length;
startIndex = i;
}
}
// 将i更新为j,跳过已经检查过的部分
i = j;
break;
}
j++;
}
}
// 返回最长神奇数列
return inp.substring(startIndex, startIndex + maxLength);
}
三、算法流程分析
外层循环遍历
- 使用
for循环,以i作为索引,从0开始遍历整个字符串,直到i < n。这里的i代表了每次尝试寻找神奇数列的起始点。在每次循环中,我们都将重新探索从当前i位置开始的子串是否包含更长的神奇数列。
内层循环探索
- 对于每个
i,初始化j = i,然后开始while循环。只要j小于n,循环就会持续进行。在这个循环中,我们开始探索从i到j这部分子串的特性。 - 在循环内部,首先计算当前从
i到j的子串长度length,计算公式为j - i + 1。这个长度值将用于后续判断是否满足神奇数列的条件。
神奇数列条件判断与更新
- 接着,通过
if (j == n - 1 || inp.charAt(j) == inp.charAt(j + 1))来检查是否满足神奇数列可能的结束条件。这里有两种情况:一是当j已经到达字符串倒数第二个位置(j == n - 1),因为此时已经无法再检查下一个相邻字符对,所以也需要进行判断;另一种情况是当当前字符inp.charAt(j)和下一个字符inp.charAt(j + 1)相等时,这可能意味着神奇数列的结束(因为神奇数列是 0 和 1 交替出现的)。 - 当满足上述结束条件之一时,进一步检查子串长度
length是否大于等于3。如果是,说明当前子串有可能是一个神奇数列。 - 然后,再检查
length是否大于当前记录的最长神奇数列长度maxLength。如果大于,就更新maxLength为当前长度length,并将startIndex更新为当前的起始索引i。这样就找到了一个新的、可能更长的神奇数列。
索引调整与下一轮准备
- 当满足神奇数列结束条件后,将
i的值更新为j,跳过已经检查过的子串部分,避免重复检查。然后break语句跳出内层while循环,准备进行下一次外层for循环。
结果返回
- 最后,当外层
for循环结束后,根据找到的最长神奇数列的起始索引startIndex和长度maxLength,使用inp.substring(startIndex, startIndex + maxLength)从原字符串中提取并返回最长的神奇数列。这个子串就是我们最终要找的结果。
四、时间复杂度分析
- 外层循环 外层
for循环遍历整个字符串,时间复杂度为 ,其中n是字符串的长度。 - 内层循环 内层
while循环在最坏情况下也会遍历整个字符串(虽然在实际中会提前跳出),但平均来看,它的时间复杂度也是 。所以整个算法的时间复杂度是 。
五、改进思考
- 优化方向 可以考虑使用更高效的数据结构或算法来降低时间复杂度。例如在发现连续相同字符时,利用一些数学规律来更快地计算当前子串的长度,而不是每次都通过
j - i + 1来计算。 - 空间复杂度考虑 当前代码的空间复杂度较低,主要是几个常数级别的变量。但如果采用额外的数据结构来优化,需要注意空间复杂度的平衡,避免因过度使用空间而导致性能下降。 总之,这段代码虽然能够正确地解决寻找最长神奇数列的问题,但在时间复杂度方面还有一定的优化空间,可以通过进一步的分析和改进来提高算法的效率。