问题描述
小F是一个好学的中学生,今天他学习了数列的概念。他在纸上写下了一个由 0 和 1 组成的正整数序列,长度为 n。这个序列中的 1 和 0 交替出现,且至少由 3 个连续的 0 和 1 组成的部分数列称为「神奇数列」。例如,10101 是一个神奇数列,而 1011 不是。现在,小F想知道在这个序列中,最长的「神奇数列」是哪一个。你能帮他找到吗?
如果有多个神奇数列,那么输出最先出现的一个。
测试样例
样例1:
输入:
inp = "0101011101"
输出:'010101'
样例2:
输入:
inp = "1110101010000"
输出:'10101010'
样例3:
输入:
inp = "1010101010101010"
输出:'1010101010101010'
解题思路
-
交替数列的特性:
- 神奇数列的定义是数列中的
0和1必须交替出现,且长度至少为 3。 - 比如:
010101和101010都是有效的神奇数列。 - 任何不符合交替的数列都不是神奇数列。
- 神奇数列的定义是数列中的
-
步骤:
- 我们需要在输入字符串中找到所有可能的交替子序列,并比较它们的长度,最终返回最长的那个。
- 为了提高效率,我们可以通过遍历字符串并从每个位置开始扩展,找到每个可能的交替子序列。
-
详细步骤:
- 使用一个外层循环遍历字符串的每个字符。
- 在每次外层循环中,构建一个新的子序列,检查后续字符是否交替。
- 如果当前字符与前一个字符不同,则继续扩展当前子序列;如果相同,则结束当前子序列。
- 对每个子序列的长度进行比较,保存最长的交替子序列。
- 只保留长度大于等于 3 的神奇数列。
-
返回结果:
- 输出找到的最长神奇数列。如果没有符合条件的数列,返回空字符串。
Java代码实现
public class Main {
public static String solution(String inp) {
int n = inp.length();
String longest = "";
for (int i = 0; i < n - 2; i++) {
StringBuilder current = new StringBuilder();
current.append(inp.charAt(i));
for (int j = i + 1; j < n; j++) {
if (inp.charAt(j) != current.charAt(current.length() - 1)) {
current.append(inp.charAt(j));
} else {
break;
}
}
if (current.length() >= 3 && current.length() > longest.length()) {
longest = current.toString();
}
}
return longest;
}
public static void main(String[] args) {
System.out.println(solution("0101011101").equals("010101"));
System.out.println(solution("1110101010000").equals("10101010"));
System.out.println(solution("1010101010101010").equals("1010101010101010"));
}
}
解题步骤和思路总结
- 初始化变量:定义一个
longest字符串,用于存储当前最长的交替子序列。使用StringBuilder来构建当前正在检查的交替子序列。 - 遍历字符串:外层循环遍历字符串的每个字符,内层循环从当前字符开始,尝试构建一个交替子序列。如果后续字符交替出现,则继续添加到
current中。 - 判断交替性:在内层循环中,检查当前字符是否与前一个字符不同。如果是交替的,则继续;如果相同,则结束当前子序列的扩展。
- 更新最长神奇数列:每次构建完成一个子序列时,检查其长度是否大于等于 3 且是否更长,若是,则更新
longest。 - 返回结果:循环结束后,
longest即为最长的交替数列。
时间复杂度分析
- 时间复杂度:
O(n^2),其中n是输入字符串的长度。因为外层循环遍历每个字符,内层循环遍历后续字符来构建交替数列,在最坏情况下需要两层循环来处理所有子序列。 - 空间复杂度:
O(n),用于存储当前的交替子序列以及最长的交替子序列。
结论
通过该方法,我们能够高效地找出最长的交替神奇数列。尽管时间复杂度为 O(n^2),但由于该问题的输入长度通常不特别大,这种解法能够在合理的时间内完成任务。