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

39 阅读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'

1. 问题分析

题目要求从一个由 '0''1' 组成的字符串中找出最长的“神奇数列”,而神奇数列的定义是交替的子序列,并且长度至少为 3。

交替数列定义:

  • 数字 '0' 和 '1' 必须交替出现。
  • 例如:"010101""101010" 都是交替数列。
  • 不符合的情况如:"1101" 或 "0010",因为存在连续相同的数字(例如 "11" 或 "00")。

神奇数列的定义:

  • 神奇数列不仅仅是交替数列,还要求其长度至少为 3。

2. 解题思路

为了找到最长的交替数列,且该数列的长度至少为 3,解题思路如下:

1) 遍历字符串

从字符串的每个字符开始,检查从当前位置开始的子序列是否是交替的。

2) 判断交替子序列

对于每个起始位置,我们从当前位置开始检查后续的字符是否交替。具体来说,如果当前位置的字符和下一个字符不同(即 inp[i] != inp[i + 1]),则说明当前字符和下一个字符是交替的,继续检查下一个字符,直到找到一个不交替的位置或者到达字符串的末尾。

3) 记录最长的交替数列

每次发现一个交替的子序列时,检查它的长度:

  • 如果该子序列的长度至少为 3,并且比当前记录的最长交替数列还长,就更新最长交替数列的长度和起始位置。
  • 如果长度小于 3,则忽略该子序列。

4) 最终返回结果

遍历完所有字符后,返回最长的交替数列。

3. 具体实现

代码实现

def solution(inp):
    max_length = 0  # 用于记录最长神奇数列的长度
    max_start = 0   # 用于记录最长神奇数列的起始位置
    
    # 遍历字符串
    for i in range(len(inp)):
        # 检查从 i 开始的子序列是否是神奇数列
        length = 1  # 从当前位置开始,至少有一个字符
        while i + length < len(inp) and inp[i + length] != inp[i + length - 1]:
            length += 1
        
        # 如果长度大于等于3,更新最长神奇数列的信息
        if length >= 3:
            if length > max_length:
                max_length = length
                max_start = i
    
    # 返回最长的神奇数列
    return inp[max_start:max_start + max_length]
    
if __name__ == "__main__":
    # Add your test cases here

    print(solution("0101011101") == "010101")

代码分析:

  1. 变量初始化

    • max_length 初始化为 0,用于记录当前找到的最长交替数列的长度。
    • max_start 初始化为 0,用于记录最长交替数列的起始位置。
  2. 外层循环

    • 使用 for i in range(len(inp)) 遍历字符串的每一个位置。每次循环开始时,我们从当前位置 i 开始检查交替数列。
  3. 内层 while 循环

    • 内层 while 循环检查从当前位置开始的子序列是否交替。具体来说,判断当前位置 i + length 和 i + length - 1 位置的字符是否不同。
    • 如果不同,则 length 自增,表示这个交替数列继续增长。
  4. 长度判断

    • 每次找到一个交替子序列后,检查其长度是否大于等于 3。如果是,则继续判断是否需要更新最长的交替数列。
    • 如果当前的交替数列长度大于 max_length,则更新 max_length 和 max_start
  5. 返回最长交替数列

    • 遍历结束后,返回从 max_start 开始、长度为 max_length 的子串。

4. 时间和空间复杂度分析

1) 时间复杂度

  • 外层循环遍历了字符串的每个字符,时间复杂度为 O(n),其中 n 是字符串的长度。
  • 内层 while 循环在最坏情况下遍历整个字符串一次,但每个字符最多被访问一次。因此,整体时间复杂度是 O(n)

2) 空间复杂度

  • 该算法只用了常数的额外空间来存储 max_lengthmax_start 和一些临时变量。所以空间复杂度为 O(1)

5. 优化考虑

1) 提前退出循环

如果我们已经找到了一个长度为 n 的交替数列,而当前的 i 已经接近字符串末尾,那么即使往后继续检查,也不会有更长的交替子序列。因此,在某些情况下,可以通过提前退出来减少不必要的计算。

2) 改进 while 循环

当前的 while 循环的时间复杂度是线性的,但它的效率可以进一步提升。如果我们能在发现不交替的地方就直接跳过一些位置,可能会进一步减少计算量。然而,目前的算法已经是比较简洁且高效的。