AI刷题128 找出最长的神奇数列|豆包MarsCode AI刷题

87 阅读4分钟

寻找最长“神奇数列”的问题解析


问题描述

小乐学习了数列的概念,并书写了一个由 01 组成的整数数列。问题要求从中找到最长的“神奇数列”。以下是具体定义和要求:

  1. 神奇数列定义

    • 数列中 01 必须交替出现。
    • 最短的神奇数列长度为 3。
  2. 输出要求

    • 在输入数列中,找出最长的神奇数列。
    • 若有多个符合条件的数列,输出最先出现的那一个。
  3. 输入输出示例

    • 输入:"0101011101",输出:"010101"
    • 输入:"1110101010000",输出:"1010101"

解题分析

核心思路

  1. 枚举起点

    • 遍历字符串的每一个字符,尝试从该字符作为起点,寻找“神奇数列”。
  2. 交替检测

    • 从当前起点开始,依次检测每一位字符,确保它与前一位满足 01 交替的规则。
  3. 记录最长子串

    • 当发现一个符合条件的子串时,与当前记录的最长子串长度进行比较。
    • 若长度更长,则更新结果;若长度相同,则保持原有的最先出现的子串。

解题思路拆解

  1. 嵌套循环实现搜索

    • 外层循环:从每个字符开始,枚举起点。
    • 内层循环:从当前起点向后扩展,验证是否符合“神奇数列”的条件。
  2. 规则验证

    • 当前字符是否满足交替变化:判断前一位字符与当前字符差值是否为 1。
    • 若条件不满足,则结束本轮扩展。
  3. 长度和结果更新

    • 每次发现新的候选子串时,记录长度和具体子串内容。

代码详解

以下为完整 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. 最先出现原则

  • 代码逻辑中,当发现长度相等的新子串时,保持原来的子串不变,默认输出最先找到的那个子串。

复杂度分析

  1. 时间复杂度

    • 外层循环:遍历字符串每个字符,复杂度 O(n)。
    • 内层循环:对每个起点,从当前位置向后扩展,最坏情况复杂度 O(n2)。

    总体时间复杂度:O(n^2)。

  2. 空间复杂度

    • 使用少量额外变量保存临时子串和结果,空间复杂度为 O(1)。

测试与验证

测试用例 1

  • 输入:"0101011101"

  • 过程:

    • 从起点 0 开始,扩展出子串 010101
    • 此后所有扩展均未超过长度 6。
  • 输出:"010101"

测试用例 2

  • 输入:"1110101010000"

  • 过程:

    • 从起点 1 开始,最长子串为 1010101
  • 输出:"1010101"

测试用例 3

  • 输入:"101010101010"

  • 过程:

    • 从起点 0 开始,扩展整个字符串。
  • 输出:"101010101010"


优化与思考

优化方向

  1. 避免重复计算

    • 当前实现中,每次从起点开始扩展,需要重复检测部分字符。
    • 可通过双指针法或滑动窗口方法优化,将时间复杂度降至 O(n)。
  2. 规则判定改进

    • 当前逻辑通过逐字符比较,可尝试直接统计连续交替段的长度,提高效率。

个人思考

  1. 代码的简化与可读性

    • 初学者实现逻辑较直观,但对较长字符串的处理效率可能不足。
    • 代码结构清晰,逻辑易懂,但存在冗余检测。
  2. 问题扩展

    • 类似问题可扩展到其他字符模式匹配,比如查找特定规律的字符串段。
    • 学习本题的实现思路后,可在复杂模式匹配任务中灵活运用。

通过以上解析与实现,问题得到了较为全面的解决,同时也为后续类似的字符串模式匹配问题提供了启发和参考。