寻找最长“神奇数列”的问题解析
问题描述
小乐学习了数列的概念,并书写了一个由 0 和 1 组成的整数数列。问题要求从中找到最长的“神奇数列”。以下是具体定义和要求:
-
神奇数列定义:
- 数列中
0和1必须交替出现。 - 最短的神奇数列长度为 3。
- 数列中
-
输出要求:
- 在输入数列中,找出最长的神奇数列。
- 若有多个符合条件的数列,输出最先出现的那一个。
-
输入输出示例:
- 输入:
"0101011101",输出:"010101"。 - 输入:
"1110101010000",输出:"1010101"。
- 输入:
解题分析
核心思路
-
枚举起点:
- 遍历字符串的每一个字符,尝试从该字符作为起点,寻找“神奇数列”。
-
交替检测:
- 从当前起点开始,依次检测每一位字符,确保它与前一位满足
0和1交替的规则。
- 从当前起点开始,依次检测每一位字符,确保它与前一位满足
-
记录最长子串:
- 当发现一个符合条件的子串时,与当前记录的最长子串长度进行比较。
- 若长度更长,则更新结果;若长度相同,则保持原有的最先出现的子串。
解题思路拆解
-
嵌套循环实现搜索:
- 外层循环:从每个字符开始,枚举起点。
- 内层循环:从当前起点向后扩展,验证是否符合“神奇数列”的条件。
-
规则验证:
- 当前字符是否满足交替变化:判断前一位字符与当前字符差值是否为 1。
- 若条件不满足,则结束本轮扩展。
-
长度和结果更新:
- 每次发现新的候选子串时,记录长度和具体子串内容。
代码详解
以下为完整 Java 实现:
核心代码
public static String solution(String inp) {
// 初始化变量
String temp = "", result = "";
int leng = 0;
// 外层循环:枚举起点
for (int i = 0; i < inp.length(); i++) {
temp = ""; // 初始化当前子串
// 内层循环:从当前起点扩展
for (int j = i; j < inp.length(); j++) {
if (temp == "") { // 初始化子串首字符
temp += inp.charAt(j);
} else {
// 判断是否满足交替规则
if (Math.abs(temp.charAt(j - i - 1) - inp.charAt(j)) == 1) {
temp += inp.charAt(j); // 符合规则,添加当前字符
continue;
} else {
break; // 不满足规则,终止扩展
}
}
}
// 更新最长“神奇数列”记录
if (temp.length() > leng && temp.length() >= 3) {
result = temp;
leng = temp.length();
}
}
// 返回结果
return result;
}
关键实现点解析
1. 子串的生成与扩展
-
每次从起点开始扩展子串,通过内层循环不断检查当前字符是否与前一字符交替。
-
判断交替规则的核心逻辑:
if (Math.abs(temp.charAt(j - i - 1) - inp.charAt(j)) == 1)- 比较当前字符与上一字符的差值是否为
1。 - 巧妙利用
ASCII值来判断是否交替。
- 比较当前字符与上一字符的差值是否为
2. 子串记录与更新
-
通过变量
leng保存当前最长子串的长度,并实时比较更新。 -
确保符合条件的子串最短长度为 3:
if (temp.length() > leng && temp.length() >= 3)
3. 最先出现原则
- 代码逻辑中,当发现长度相等的新子串时,保持原来的子串不变,默认输出最先找到的那个子串。
复杂度分析
-
时间复杂度:
- 外层循环:遍历字符串每个字符,复杂度 O(n)。
- 内层循环:对每个起点,从当前位置向后扩展,最坏情况复杂度 O(n2)。
总体时间复杂度:O(n^2)。
-
空间复杂度:
- 使用少量额外变量保存临时子串和结果,空间复杂度为 O(1)。
测试与验证
测试用例 1
-
输入:
"0101011101" -
过程:
- 从起点
0开始,扩展出子串010101。 - 此后所有扩展均未超过长度 6。
- 从起点
-
输出:
"010101"。
测试用例 2
-
输入:
"1110101010000" -
过程:
- 从起点
1开始,最长子串为1010101。
- 从起点
-
输出:
"1010101"。
测试用例 3
-
输入:
"101010101010" -
过程:
- 从起点
0开始,扩展整个字符串。
- 从起点
-
输出:
"101010101010"。
优化与思考
优化方向
-
避免重复计算:
- 当前实现中,每次从起点开始扩展,需要重复检测部分字符。
- 可通过双指针法或滑动窗口方法优化,将时间复杂度降至 O(n)。
-
规则判定改进:
- 当前逻辑通过逐字符比较,可尝试直接统计连续交替段的长度,提高效率。
个人思考
-
代码的简化与可读性:
- 初学者实现逻辑较直观,但对较长字符串的处理效率可能不足。
- 代码结构清晰,逻辑易懂,但存在冗余检测。
-
问题扩展:
- 类似问题可扩展到其他字符模式匹配,比如查找特定规律的字符串段。
- 学习本题的实现思路后,可在复杂模式匹配任务中灵活运用。
通过以上解析与实现,问题得到了较为全面的解决,同时也为后续类似的字符串模式匹配问题提供了启发和参考。