面试题 01.09. 字符串轮转
题目描述
字符串轮转。给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottle是erbottlewat旋转后的字符串)。
示例1:
输入:s1 = "waterbottle", s2 = "erbottlewat" 输出:True
示例2:
输入:s1 = "aa", "aba" 输出:False
提示:
- 字符串长度在[0, 100000]范围内。
说明:
- 你能只调用一次检查子串的方法吗?
解法
方法一:字符串匹配
思考
旋转即把某前缀挪到末尾。枚举所有切割点再比较,共 \(n\) 次、每次 \(O(n)\),在长度相等时可行,但重复比较较多。
长度不等则必不是旋转。长度相等时,\(s_1+s_1\) 覆盖 \(s_1\) 的全部旋转,于是问题化为一次子串判定:\(s_2\) 是否出现在 \(s_1+s_1\) 中。
代码先比长度,再用 s2 in s1 * 2 完成包含检查,与上述观察一致。
首先,如果字符串 \(s1\) 和 \(s2\) 长度不相等,那么肯定不是旋转字符串。
其次,如果字符串 \(s1\) 和 \(s2\) 长度相等,那么将两个 \(s1\) 连接,得到的 \(s1 + s1\) 这个字符串一定包含了 \(s1\) 旋转的所有情况,这时候我们只要判断 \(s2\) 是否是 \(s1 + s1\) 的子串即可。
# 成立
s1 = "aba"
s2 = "baa"
s1 + s1 = "abaaba"
^^^
# 不成立
s1 = "aba"
s2 = "bab"
s1 + s1 = "abaaba"
时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。其中 \(n\) 为字符串 \(s1\) 的长度。
1 2 3 | |
1 2 3 4 5 | |
1 2 3 4 5 6 | |
1 2 3 | |
1 2 3 | |
1 2 3 4 5 | |
1 2 3 4 5 | |