难度: Easy
字符串轮转。给定两个字符串s1
和s2
,请编写代码检查s2
是否为s1
旋转而成(比如,waterbottle
是erbottlewat
旋转后的字符串)。
示例1:
输入:s1 = "waterbottle", s2 = "erbottlewat" 输出:True
示例2:
输入:s1 = "aa", s2 = "aba" 输出:False
提示:
- 字符串长度在[0, 100000]范围内。
说明:
- 你能只调用一次检查子串的方法吗?
难度: Easy
字符串轮转。给定两个字符串s1
和s2
,请编写代码检查s2
是否为s1
旋转而成(比如,waterbottle
是erbottlewat
旋转后的字符串)。
示例1:
输入:s1 = "waterbottle", s2 = "erbottlewat" 输出:True
示例2:
输入:s1 = "aa", s2 = "aba" 输出:False
提示:
说明:
运行时间: 19 ms
内存: 16.3 MB
class Solution: def isFlipedString(self, s1: str, s2: str) -> bool: return len(s1) == len(s2) and s1 in (s2 + s2)
解题思路是基于一个简单的观察:如果字符串s2是字符串s1的一个轮转,那么s2必然是由s1两部分的某种组合(前半段和后半段)构成的。因此,如果我们将s1与自身拼接,形成新字符串s1s1,那么s2必须是s1s1的一个子字符串。这种方法首先检查两个字符串长度是否相等,若不相等,则s2不可能是s1的轮转。如果长度相等,再检查s2是否为s1s1的子串。
时间复杂度: O(n)
空间复杂度: O(n)
# 定义Solution类 class Solution: def isFlipedString(self, s1: str, s2: str) -> bool: # 首先检查两个字符串的长度是否相等 if len(s1) != len(s2): return False # 将s1与自身连接,并检查s2是否为结果字符串的子串 return s2 in (s2 + s2)
假设s1是'abcde',任意的轮转可以看作是将s1从某个点断开成为两个部分,然后交换这两部分的位置。例如,如果我们将'abcde'在c处断开,得到'abc'和'de',然后交换这两部分的位置,得到'deabc',这就是一个轮转。如果我们将s1与自身拼接,得到'abcdeabcde',无论原字符串s1如何断开和重组,得到的轮转结果都会作为这个新字符串的一个子串出现。这是因为拼接后的字符串包含了s1所有可能的轮转组合。
检查s1和s2的长度是否相等是必要的初步步骤,因为只有长度相等的字符串才可能是彼此的轮转。然而,仅仅长度相等并不能保证s2就一定是s1的轮转。例如,s1='abcde'和s2='eabcd'长度相同,并且s2是s1的轮转;而s1='abcde'和s2='edcba'虽然长度相同,但s2不是s1的轮转。所以,长度检查后,还需要进一步验证s2是否为s1s1的子字符串来确保s2确实是s1的轮转。
确实,这里有一个笔误。正确的表达应该是检查s2是否为新字符串`(s1 + s1)`的子串。代码应改为`return s2 in (s1 + s1)`。这个表达式正确地将s1与自己拼接,并检查s2是否为这个新字符串的子串,从而验证s2是否是s1的轮转。