题目描述
小F是一个好学的中学生,今天他学习了数列的概念。他在纸上写下了一个由0和1组成的正整数序列,长度为n。这个序列中的1和0交替出现,且至少由3个连续的0和1组成的部分数列称为“神奇数列”。例如,10101是一个神奇数列,而1011不是。现在,小F想知道在这个序列中,最长的“神奇数列”是哪一个。你能帮他找到吗?
如果有多个神奇数列,那么输出最先出现的一个。
解决方案
我们需要找到一个序列中符合“神奇数列”定义的最长子序列。可以通过遍历序列来检查每个可能的子序列,判断其是否符合条件,并记录最长的符合条件的子序列。
分析思路
-
初始化变量:
- 记录当前最长的“神奇数列”的起始位置和长度。
- 临时变量用于记录当前正在检查的子序列的长度和起始位置。
-
遍历序列:
- 从头到尾遍历序列,检查每一对相邻字符,判断是否满足交替出现的条件。
- 如果满足条件,则更新当前子序列的长度。
- 如果不满足条件,则检查当前子序列的长度是否符合“神奇数列”的定义(即长度至少为5)。如果符合,则更新最长的“神奇数列”的起始位置和长度。
-
处理尾部的情况:
- 在遍历完成后,检查最后一个子序列是否符合“神奇数列”的定义。
-
输出结果:
- 根据最长的“神奇数列”的起始位置和长度,输出该子序列。如果没有符合条件的子序列,则输出空字符串。
代码实现
java
public class MagicSubsequence {
public static void main(String[] args) {
String sequence = "1001011001010101";
System.out.println("最长的神奇数列是: " + findLongestMagicSequence(sequence));
}
public static String findLongestMagicSequence(String s) {
int n = s.length();
int maxLength = 0;
int start = -1;
int currentLength = 0;
int currentStart = -1;
for (int i = 1; i < n; i++) {
if ((s.charAt(i - 1) == '0' && s.charAt(i) == '1') || (s.charAt(i - 1) == '1' && s.charAt(i) == '0')) {
if (currentLength == 0) {
currentStart = i - 1;
}
currentLength++;
} else {
if (currentLength >= 4) {
if (currentLength > maxLength) {
maxLength = currentLength;
start = currentStart;
}
}
currentLength = 0;
}
}
// 处理尾部情况
if (currentLength >= 4) {
if (currentLength > maxLength) {
maxLength = currentLength;
start = currentStart;
}
}
return start == -1 ? "" : s.substring(start, start + maxLength + 1);
}
}
代码解释
-
初始化变量:
maxLength用于记录当前最长“神奇数列”的长度,初始值为0。start用于记录当前最长“神奇数列”的起始位置,初始值为-1。currentLength用于记录当前正在检查的子序列的长度,初始值为0。currentStart用于记录当前正在检查的子序列的起始位置,初始值为-1。
-
遍历序列:
- 使用
for循环从序列的第二个字符开始遍历,检查每对相邻字符。 - 如果两个字符交替出现,则更新当前子序列的长度和起始位置。
- 如果两个字符不交替出现,则检查当前子序列的长度是否为“神奇数列”,如果是,则更新最长的“神奇数列”的长度和起始位置。
- 使用
-
处理尾部情况:
- 在遍历结束后,检查最后一个子序列是否为“神奇数列”,如果是,则更新最长的“神奇数列”的长度和起始位置。
-
输出结果:
- 根据
maxLength和start,返回最长的“神奇数列”。如果没有符合条件的子序列,则返回空字符串。
- 根据
复杂度分析
- 时间复杂度:因为我们需要遍历整个字符串,每个字符只处理一次,因此时间复杂度为O(n),其中n是字符串的长度。
- 空间复杂度:我们只使用了常数级别的额外空间(用于存储索引和长度),因此空间复杂度为O(1)。
总结
通过以上步骤和实现,我们可以在给定的字符串中高效地找到最长的“神奇数列”。这个方法利用了线性扫描和条件判断,能够在一次遍历中解决问题。