问题
问题描述
小F是一个好学的中学生,今天他学习了数列的概念。他在纸上写下了一个由 0
和 1
组成的正整数序列,长度为 n
。这个序列中的 1
和 0
交替出现,且至少由 3 个连续的 0
和 1
组成的部分数列称为「神奇数列」。例如,10101
是一个神奇数列,而 1011
不是。现在,小F想知道在这个序列中,最长的「神奇数列」是哪一个。你能帮他找到吗?
如果有多个神奇数列,那么输出最先出现的一个。
测试样例
样例1:
输入:
inp = "0101011101"
输出:'010101'
样例2:
输入:
inp = "1110101010000"
输出:'10101010'
样例3:
输入:
inp = "1010101010101010"
输出:'1010101010101010'
分析
问题理解
我们需要在一个由 0
和 1
组成的字符串中找到最长的「神奇数列」。神奇数列的定义是:
- 由
0
和1
交替出现。 - 至少包含 3 个连续的
0
和1
。这意味着数列中至少要有 3 个连续的0
或1
,并且这些0
和1
是交替出现的。比如10101
是神奇数列,而1010
就不是。
数据结构选择
由于我们处理的是字符串,可以直接使用字符串操作。
算法步骤
- 遍历字符串:从字符串的第一个字符开始,逐个检查字符。
- 检测交替模式:对于每个字符,检查它是否与前一个字符不同,如果是,则继续检查下一个字符是否与当前字符不同,以此类推。
- 记录最长神奇数列:在检测到交替模式(交替模式在本题中指的是序列中的
0
和1
交替出现)时,记录当前的子串长度,并与之前记录的最长长度进行比较。如果当前长度更长,则更新最长神奇数列的起始和结束位置。 - 返回结果:遍历结束后,返回最长的神奇数列。
关键点
- 如何高效地检测交替模式。
- 如何记录和更新最长神奇数列的起始和结束位置。
这道题目综合运用了字符串处理和双指针算法知识,是一道典型的字符串处理问题,适合练习字符串操作和算法优化的同学。
思路说明
题目要求找出由 0
和 1
交替组成的、长度至少为 3 的最长子序列。我们可以通过遍历字符串,使用双指针来识别和记录这些交替出现的子序列。具体来说,我们使用两个指针 i
和 j
,其中 i
指向当前子序列的开始,j
用于扩展子序列,直到遇到与前一个字符相同的字符为止。通过这种方式,我们可以找到所有符合条件的子序列,并记录其中最长的那个。
解题过程
- 初始化:
- 初始化指针
i
为 0,表示当前子序列的起始位置。 - 初始化变量
ans
为空字符串,用于存储最长的神奇数列。
- 初始化指针
- 遍历字符串:
- 使用
while
循环遍历字符串,直到i
达到字符串的长度。 - 初始化指针
j
为i + 1
,表示当前子序列的下一个字符。
- 使用
- 扩展子序列:
- 使用
while
循环,当j
未超出字符串长度且inp[j]
不等于inp[j - 1]
时,继续扩展子序列。 - 每次扩展后,
j
增加 1。
- 使用
- 更新最长子序列:
- 如果当前子序列的长度
j - i
大于ans
的长度,则更新ans
为当前子序列chars[i..j].iter().collect()
。 - 更新
i
为j
,继续寻找下一个子序列。
- 如果当前子序列的长度
- 返回结果:
- 如果最终找到的最长子序列长度小于 3,则返回空字符串。
- 否则,返回
ans
。
复杂度分析
- 时间复杂度:
- 遍历字符串一次,时间复杂度为 O(n),其中 n 是字符串的长度。
- 在每次遍历中,
j
指针最多移动 n 次,因此总体时间复杂度为 O(n)。
- 空间复杂度:
- 只使用了常数级别的额外空间,空间复杂度为 O(1)。
知识点扩展
- 字符串处理:
- 字符串的基本操作,如遍历、切片等。
- 双指针技巧在字符串处理中的应用,用于高效地识别和处理子序列。
- 双指针算法:
- 双指针算法是一种常用的优化技巧,适用于需要在数组或字符串中寻找特定模式的场景。
- 在本题中,双指针
i
和j
分别用于标记子序列的起始和结束位置,通过这种方式可以高效地找到符合条件的子序列。
解答
1 | fn solution(inp: &str) -> String { |
- 字符串处理:
- 在 Rust 中,字符串不能像 Python 那样直接用下标访问字符
- 需要先将字符串转换为字符数组:let chars: Vec
= inp.chars().collect() - 切片操作需要使用 collect() 来收集字符:chars[i..j].iter().collect()
- 变量声明:
- Rust 需要使用 mut 关键字声明可变变量
- 使用 String::new() 创建空字符串
- 循环和条件:
- while 循环的语法基本相同
- 条件判断不需要括号
- 字符串操作:
- Python 的字符串切片 inp[i:j] 变成了 Rust 的 chars[i..j].iter().collect()
- 清空字符串使用 ans.clear() 而不是赋值空字符串