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

56 阅读5分钟

解题思路:寻找最长的「神奇数列」

问题背景与分析

本题的目标是从一个仅由 01 组成的正整数序列中,找到最长的符合以下条件的子串:

  1. 交替性:子串中的字符必须是 01 交替出现,不能存在连续的两个相同字符。
  2. 最小长度:子串的长度必须大于等于 3。

如果有多个子串长度相同,返回最先出现的那个子串。如果没有符合条件的子串,则返回空字符串。


解题的核心点

这是一道典型的字符串模式识别问题,核心在于高效定位子串的边界并检查条件。本题有几个关键点需要分析:

  1. 交替性检查

    • 字符串交替意味着任意两个相邻字符不同。如果出现连续的两个相同字符,当前的交替子串就结束了。
  2. 子串长度

    • 子串的长度必须大于等于 3,这是一个硬性条件。需要在交替性检查的基础上,进一步确保子串长度满足条件。
  3. 最长子串

    • 我们需要找到满足条件的最长子串,这要求我们在遍历时实时记录长度最大的交替子串。
  4. 优先返回最先出现的子串

    • 如果存在多个符合条件的最长子串,返回第一个找到的子串即可。通过比较和记录起始位置,可以实现这一点。

解题思路的构建

为了解决问题,我们可以使用滑动窗口技术,这是处理字符串中连续子串问题的常用方法。滑动窗口通过动态调整窗口的起始和结束位置,能够高效定位目标子串。

滑动窗口法的核心思路
  1. 初始化窗口

    • 定义两个指针 startend,分别表示窗口的起始和结束位置。
    • start 初始化为 0,end 从 1 开始遍历整个字符串。
  2. 窗口扩展条件

    • 检查当前字符与前一个字符是否不同。
    • 如果不同,则窗口继续扩展。
    • 如果相同,说明交替性被打破,此时需要重置窗口起始位置,将 start 更新为当前 end 的位置。
  3. 记录最长子串

    • 当窗口长度(end - start + 1)大于等于 3 时,检查当前子串是否比之前记录的最长子串更长:
      • 如果更长,更新最长子串的长度和内容。
      • 如果长度相同,保留最先出现的子串。
  4. 遍历结束后返回结果

    • 如果找到符合条件的最长子串,返回它;
    • 如果没有符合条件的子串,返回空字符串。

算法流程

算法可以分为以下几个步骤:

  1. 初始化相关变量:

    • max_length:记录当前最长子串的长度,初始值为 0。
    • longest_sequence:记录当前最长子串的内容,初始值为空字符串。
    • start:窗口起始位置,初始值为 0。
  2. 遍历字符串:

    • 从第二个字符开始,用 end 指针遍历整个字符串。
    • 比较 inp[end]inp[end - 1]
      • 如果不同,窗口继续扩展。
      • 如果相同,更新 start = end,重新开始新窗口。
  3. 更新结果:

    • 每次窗口长度 end - start + 1 大于等于 3 时:
      • 如果当前子串长度超过 max_length,更新最长子串及其长度。
      • 如果当前长度等于 max_length,跳过更新,因为我们优先保留最先出现的子串。
  4. 返回结果:

    • 遍历完成后,返回 longest_sequence
def find_longest_magic_sequence(inp: str) -> str:
    n = len(inp)
    if n < 3:  # 长度不足 3,直接返回空字符串
        return ""
    
    max_length = 0
    longest_sequence = ""
    
    start = 0  # 滑动窗口的起始位置
    for end in range(1, n):
        # 如果当前字符和前一个字符相同,窗口从当前字符重新开始
        if inp[end] == inp[end - 1]:
            start = end
        
        # 检查当前窗口的长度是否满足条件
        if end - start + 1 >= 3:
            current_length = end - start + 1
            if current_length > max_length:
                max_length = current_length
                longest_sequence = inp[start:end + 1]
    
    return longest_sequence


复杂度分析

时间复杂度

  • 每个字符只会被访问一次,因此算法的时间复杂度为 (O(n)),其中 (n) 是输入字符串的长度。

空间复杂度

  • 我们只使用了常量级别的额外空间(用于记录窗口位置和结果),因此空间复杂度为 (O(1))。

思路的可扩展性

  • 处理更复杂的交替规则:如果需要处理的不仅仅是 01,而是任意两个不同字符的交替,解法可以很容易扩展。
  • 其他长度要求:通过修改条件判断,轻松支持其他长度限制,比如要求最短长度为 5。
  • 多次查找:如果需要找到所有满足条件的最长子串,可以通过记录每次的起始和结束位置来实现。

总结

滑动窗口法是一种非常高效的字符串处理技巧,尤其适合本题这种要求定位连续子串的问题。通过维护一个动态调整的窗口,结合长度和交替性检查,我们能够快速找到符合条件的最长子串。整个算法具有良好的时间性能,适用于大规模数据的处理,是解决类似问题的通用方案。