题目描述
小F在纸上写下了一个由 0 和 1 组成的正整数序列,长度为 n。这个序列中的 1 和 0 交替出现,且至少由 3 个连续的 0 和 1 组成 的部分序列被称为「神奇数列」。
例如:
- 序列
10101是神奇数列。 - 序列
1011不是神奇数列。
现在,小F想知道在这个序列中,最长的「神奇数列」是哪一个。如果有多个神奇数列长度相同,输出最先出现的那个。
示例
样例1:
输入:inp = "0101011101"
输出:'010101'
样例2:
输入:inp = "1110101010000"
输出:'10101010'
样例3:
输入:inp = "1010101010101010"
输出:'1010101010101010'
解题思路
要找到最长的神奇数列,需要对整个字符串进行逐步扫描,检查每个子序列是否符合条件,并记录最长的符合条件的子序列。
解题步骤
-
神奇数列的判定:
- 一个子序列是神奇数列需要满足:
- 至少长度为 3。
- 每两个相邻字符交替,即
101或010的形式。
- 对此可以实现一个函数
is_magic。
- 一个子序列是神奇数列需要满足:
-
枚举子序列:
- 使用双重循环,枚举所有可能的子序列。
- 对每个子序列调用
is_magic函数进行验证。 - 如果该子序列为神奇数列且长度大于当前记录的最大长度,则更新结果。
-
时间优化:
- 虽然双层循环遍历时间复杂度为 (O(n^2)),但子序列验证成本较低,直接比较字符,保证每次验证快速结束。
代码实现
def solution(inp):
# 检查是否是神奇数列
def is_magic(seq):
if len(seq) < 3:
return False
for i in range(len(seq) - 1):
if seq[i] == seq[i + 1]: # 相邻字符不能相等
return False
return True
# 初始化变量
n = len(inp)
max_len = 0
result = ""
# 枚举所有可能的子序列
for i in range(n):
for j in range(i + 3, n + 1): # 至少长度为3
sub_seq = inp[i:j]
if is_magic(sub_seq) and len(sub_seq) > max_len:
max_len = len(sub_seq)
result = sub_seq
return result
if __name__ == "__main__":
# 测试用例
print(solution("0101011101") == "010101") # True
print(solution("1110101010000") == "10101010") # True
print(solution("1010101010101010") == "1010101010101010") # True
MarsCode发挥的作用
-
函数分离:
is_magic函数封装了神奇数列的验证逻辑,将功能模块化,使代码更清晰易懂。
-
双层循环的精确范围控制:
- 外层循环从头到尾遍历序列,内层循环从起点开始寻找符合条件的子序列,枚举范围优化为从长度至少为 3 开始。
-
判定和更新逻辑的优化:
- 在判断当前子序列是否为神奇数列后,直接通过比较长度更新结果,保证结果始终正确。
-
清晰的边界条件:
- 若序列长度不足 3,直接跳过,避免不必要的运算。
总结
本题重点在于:
- 分离判断逻辑与主流程:通过
is_magic函数实现神奇数列的判定,保持主循环逻辑简洁。 - 暴力解法的合理优化:通过设置子序列长度下限和逐步更新最长长度,避免不必要的冗余计算。
- 边界条件的处理:保证所有情况下均能返回正确结果。
代码设计合理,易读性强,适用于小规模数据场景((n \leq 10^4))。