问题描述
小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")
代码分析:
-
变量初始化:
max_length初始化为0,用于记录当前找到的最长交替数列的长度。max_start初始化为0,用于记录最长交替数列的起始位置。
-
外层循环:
- 使用
for i in range(len(inp))遍历字符串的每一个位置。每次循环开始时,我们从当前位置i开始检查交替数列。
- 使用
-
内层
while循环:- 内层
while循环检查从当前位置开始的子序列是否交替。具体来说,判断当前位置i + length和i + length - 1位置的字符是否不同。 - 如果不同,则
length自增,表示这个交替数列继续增长。
- 内层
-
长度判断:
- 每次找到一个交替子序列后,检查其长度是否大于等于 3。如果是,则继续判断是否需要更新最长的交替数列。
- 如果当前的交替数列长度大于
max_length,则更新max_length和max_start。
-
返回最长交替数列:
- 遍历结束后,返回从
max_start开始、长度为max_length的子串。
- 遍历结束后,返回从
4. 时间和空间复杂度分析
1) 时间复杂度:
- 外层循环遍历了字符串的每个字符,时间复杂度为
O(n),其中n是字符串的长度。 - 内层
while循环在最坏情况下遍历整个字符串一次,但每个字符最多被访问一次。因此,整体时间复杂度是O(n)。
2) 空间复杂度:
- 该算法只用了常数的额外空间来存储
max_length、max_start和一些临时变量。所以空间复杂度为O(1)。
5. 优化考虑
1) 提前退出循环:
如果我们已经找到了一个长度为 n 的交替数列,而当前的 i 已经接近字符串末尾,那么即使往后继续检查,也不会有更长的交替子序列。因此,在某些情况下,可以通过提前退出来减少不必要的计算。
2) 改进 while 循环:
当前的 while 循环的时间复杂度是线性的,但它的效率可以进一步提升。如果我们能在发现不交替的地方就直接跳过一些位置,可能会进一步减少计算量。然而,目前的算法已经是比较简洁且高效的。