问题分析
在这个问题中,给定一个由0和1组成的序列,我们的目标是找出最长的“神奇数列”。所谓“神奇数列”,是指由连续交替的0和1组成的子串,并且该子串长度至少为3。问题要求我们在给定的输入序列中,找到最长的交替子串,并返回该子串。如果有多个符合条件的子串,应该返回最先出现的那个。
关键点
- 交替特性:一个“神奇数列”是由0和1交替出现的子串。例如,
010101或101010都是交替子串。 - 长度要求:为了被认为是“神奇数列”,该子串必须包含至少3个字符。
- 输出要求:如果多个神奇数列的长度相同,我们需要输出最先出现的那个。
解题思路
为了找到最长的神奇数列,我们可以使用一次遍历来检查所有可能的交替子串。具体步骤如下:
- 初始化变量:我们首先初始化一些变量,包括记录当前交替子串的起始位置和结束位置的
left和right,以及记录最长交替子串的maxleft和maxright。 - 遍历序列:我们遍历整个输入序列,从第二个字符开始。如果当前字符与上一个字符相同,则表示当前交替子串已经结束,此时我们需要检查该子串的长度。如果该子串长度大于之前的最长子串,就更新最长子串的起始和结束位置。然后,重新开始新的子串。
- 检查最后一段子串:循环结束后,我们还需要检查最后一个交替子串的长度,并更新最长子串的记录。
- 返回结果:根据记录的最长子串的位置,截取该子串并返回。
代码分析
以下是解决该问题的代码实现:
public class Main {
public static String solution(String inp) {
int left = 0, right = 0;
char head = inp.charAt(0);
int length = 0;
int maxleft = 0, maxright = 0;
// 遍历整个输入序列
for (int i = 1; i < inp.length(); i++) {
// 如果当前字符和之前的字符相同,表示交替子串结束
if (inp.charAt(i) == head) {
// 检查子串长度是否满足条件,并更新最大子串
if (right - left >= 2) {
if (right - left > length) {
length = right - left;
maxleft = left;
maxright = right;
}
}
// 更新left和right指针,重新开始新的子串
left = i;
right = i;
} else {
// 否则,继续扩展当前子串
right = i;
head = inp.charAt(i);
}
}
// 检查最后一个交替子串
if (right - left >= 2 && right - left > length) {
maxleft = left;
maxright = right;
}
// 如果找到了符合条件的神奇数列,返回该子串
if(maxright - maxleft >= 2) {
return inp.substring(maxleft, maxright + 1);
} else {
return "";
}
}
public static void main(String[] args) {
// 测试
System.out.println(solution("0101011101").equals("010101"));
}
}
代码讲解
- 变量初始化:
left和right用来标记当前交替子串的起始和结束位置,head用来记录当前交替子串的第一个字符,maxleft和maxright用来存储最长交替子串的起始和结束位置,length用来记录当前最长子串的长度。 - 遍历输入字符串:我们从第二个字符开始,逐个检查输入字符串的每个字符。对于每个字符,如果它与前一个字符相同,说明交替序列结束,我们需要计算当前交替子串的长度,若长度大于当前记录的最长子串,则更新最长子串的起始和结束位置。
- 最后检查:由于遍历结束时,最后一段交替子串没有被检查,因此在循环外再次检查最后一个交替子串。
- 返回结果:最终,我们通过
maxleft和maxright来截取并返回最长的交替子串。
时间复杂度
该算法只需一次遍历输入字符串,因此时间复杂度为 O(n),其中n是输入字符串的长度。由于我们仅使用了常数额外空间来存储一些指针和长度信息,因此空间复杂度为 O(1)。
示例分析
-
输入:
"0101011101"输出:
"010101"解析:在这个例子中,最长的神奇数列是
"010101",长度为6。 -
输入:
"1110101010000"输出:
"10101010"解析:此输入中,最长的神奇数列是
"10101010",长度为8。 -
输入:
"1010101010101010"输出:
"1010101010101010"解析:该输入本身就是一个完全交替的序列,因此最长的神奇数列即为整个字符串,长度为16。
总结
该问题的核心思想是通过一次遍历来寻找交替子串,并通过记录交替子串的起始和结束位置来确保找出最长的神奇数列。在实现过程中,采用了双指针法,通过维护left和right指针来跟踪当前交替子串的范围,确保能够在O(n)的时间复杂度内解决问题。这种方法不仅高效,而且直观,适合解决类似的字符串匹配问题。