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

61 阅读5分钟

问题描述

小F是一个好学的中学生,今天他学习了数列的概念。他在纸上写下了一个由 0 和 1 组成的正整数序列,长度为 n。这个序列中的 1 和 0 交替出现,且至少由 3 个连续的 0 和 1 组成的部分数列称为「神奇数列」。例如,10101 是一个神奇数列,而 1011 不是。现在,小F想知道在这个序列中,最长的「神奇数列」是哪一个。你能帮他找到吗?

如果有多个神奇数列,那么输出最先出现的一个。


测试样例

样例1:

输入:inp = "0101011101"
输出:'010101'

样例2:

输入:inp = "1110101010000"
输出:'10101010'

样例3:

输入:inp = "1010101010101010"
输出:'1010101010101010'

题目分析

小F写下了一个由 01 组成的正整数序列,长度为 n。我们需要在这个序列中找到最长的「神奇数列」。
神奇数列的定义

  1. 序列中的 01 必须交替出现。
  2. 子序列的长度至少为 3。

题目要求
在所有可能的「神奇数列」中,找到最长的那一个,如果有多个,输出最先出现的一个。


解题思路

  1. 核心判断

    • 一个序列是否为「神奇数列」,可以通过检查相邻字符是否交替出现来实现。
    • 如果相邻的两个字符相同,则该序列不是「神奇数列」。
  2. 子序列生成

    • 我们需要检查输入字符串中所有长度至少为 3 的子序列,判断它们是否是「神奇数列」。
  3. 长度优先,位置次优先

    • 如果有多个符合条件的「神奇数列」,优先选择长度最长的;
    • 如果长度相同,则选择最先出现的一个。
  4. 暴力枚举

    • 遍历所有可能的子序列,并检查其是否为「神奇数列」。虽然时间复杂度较高,但可以保证找出正确答案。
  5. 优化(可选):

    • 采用滑动窗口方法,避免重复检查所有子序列,减少时间复杂度。

代码实现

以下是基于暴力枚举的解决方案:

def solution(inp):
    # 用于存储最长的神奇数列
    max_sequence = ""
    n = len(inp)
    
    # 遍历字符串的所有可能子序列
    for i in range(n):
        for j in range(i + 3, n + 1):  # 子序列长度至少为3
            sub_sequence = inp[i:j]
            
            # 检查子序列是否符合神奇数列条件:0和1交替出现
            if is_alternating(sub_sequence):
                # 更新最长的神奇数列
                if len(sub_sequence) > len(max_sequence):
                    max_sequence = sub_sequence
    
    return max_sequence

def is_alternating(sequence):
    # 检查序列是否0和1交替
    for k in range(1, len(sequence)):
        if sequence[k] == sequence[k - 1]:
            return False
    return True

if __name__ == "__main__":
    # 测试用例
    print(solution("0101011101") == "010101")  # True
    print(solution("1110101010000") == "10101010")  # True
    print(solution("1010101010101010") == "1010101010101010")  # True

示例解析

示例 1

输入:"0101011101"
输出:"010101"
解析

  • 子序列 010101 是最长的交替序列,符合神奇数列的定义。

示例 2

输入:"1110101010000"
输出:"10101010"
解析

  • 子序列 10101010 是最长的交替序列。

示例 3

输入:"1010101010101010"
输出:"1010101010101010"
解析

  • 整个字符串是最长的交替序列。

时间复杂度

  1. 子序列生成
    遍历每个可能的起始位置 i 和结束位置 j,需要 O(n^2) 次操作。
  2. 神奇数列判断
    每次判断子序列是否满足条件,最坏需要 O(n) 次操作。
  3. 总复杂度
    暴力方法的时间复杂度为 O(n^3)

优化思路

  1. 滑动窗口

    • 使用两个指针维护一个窗口,动态检查窗口内是否满足交替条件。
    • 当窗口内不满足条件时,调整起点指针,避免冗余检查。
  2. 时间复杂度

    • 滑动窗口法可以将复杂度降为 O(n)

滑动窗口实现

def solution(inp):
    n = len(inp)
    max_sequence = ""
    start = 0  # 滑动窗口的起点

    for end in range(1, n):
        # 检查当前窗口是否满足交替条件
        if inp[end] == inp[end - 1]:
            start = end  # 不满足交替,移动起点
        elif end - start + 1 >= 3:  # 窗口长度至少为3
            current_sequence = inp[start:end + 1]
            if len(current_sequence) > len(max_sequence):
                max_sequence = current_sequence

    return max_sequence

if __name__ == "__main__":
    # 测试用例
    print(solution("0101011101") == "010101")  # True
    print(solution("1110101010000") == "10101010")  # True
    print(solution("1010101010101010") == "1010101010101010")  # True

总结

  • 本题的关键在于理解交替序列的定义,并结合滑动窗口或暴力枚举找到最长的符合条件的子序列。
  • 暴力解法简单易懂,但复杂度较高;滑动窗口法更高效,适合更长的输入序列。