问题描述
小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写下了一个由 0 和 1 组成的正整数序列,长度为 n。我们需要在这个序列中找到最长的「神奇数列」。
神奇数列的定义:
- 序列中的
0和1必须交替出现。 - 子序列的长度至少为 3。
题目要求:
在所有可能的「神奇数列」中,找到最长的那一个,如果有多个,输出最先出现的一个。
解题思路
-
核心判断:
- 一个序列是否为「神奇数列」,可以通过检查相邻字符是否交替出现来实现。
- 如果相邻的两个字符相同,则该序列不是「神奇数列」。
-
子序列生成:
- 我们需要检查输入字符串中所有长度至少为 3 的子序列,判断它们是否是「神奇数列」。
-
长度优先,位置次优先:
- 如果有多个符合条件的「神奇数列」,优先选择长度最长的;
- 如果长度相同,则选择最先出现的一个。
-
暴力枚举:
- 遍历所有可能的子序列,并检查其是否为「神奇数列」。虽然时间复杂度较高,但可以保证找出正确答案。
-
优化(可选):
- 采用滑动窗口方法,避免重复检查所有子序列,减少时间复杂度。
代码实现
以下是基于暴力枚举的解决方案:
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"
解析:
- 整个字符串是最长的交替序列。
时间复杂度
- 子序列生成:
遍历每个可能的起始位置i和结束位置j,需要O(n^2)次操作。 - 神奇数列判断:
每次判断子序列是否满足条件,最坏需要O(n)次操作。 - 总复杂度:
暴力方法的时间复杂度为O(n^3)。
优化思路
-
滑动窗口:
- 使用两个指针维护一个窗口,动态检查窗口内是否满足交替条件。
- 当窗口内不满足条件时,调整起点指针,避免冗余检查。
-
时间复杂度:
- 滑动窗口法可以将复杂度降为
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
总结
- 本题的关键在于理解交替序列的定义,并结合滑动窗口或暴力枚举找到最长的符合条件的子序列。
- 暴力解法简单易懂,但复杂度较高;滑动窗口法更高效,适合更长的输入序列。