旋转字符串

标签: 字符串 字符串匹配

难度: Easy

给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。

s 的 旋转操作 就是将 s 最左边的字符移动到最右边。 

  • 例如, 若 s = 'abcde',在旋转一次之后结果就是'bcdea' 。

示例 1:

输入: s = "abcde", goal = "cdeab"
输出: true

示例 2:

输入: s = "abcde", goal = "abced"
输出: false

提示:

  • 1 <= s.length, goal.length <= 100
  • s 和 goal 由小写英文字母组成

Submission

运行时间: 19 ms

内存: 15.9 MB

class Solution:
    def rotateString(self, s: str, goal: str) -> bool:
        if s == goal:
           return True
        for i in range(len(s)-1):
            if s[i+1:]+s[:i+1] == goal:
                return True
        return False

Explain

这个题解采用了一种简单直接的方法来解决旋转字符串的问题。首先,它检查原字符串s和目标字符串goal是否相等,如果相等则直接返回true。如果不相等,它会遍历字符串s的每个位置,从每个位置分别进行一次旋转,即把从当前位置到字符串末尾的子字符串放到前面,从字符串开头到当前位置的子字符串放到后面。如果在任何旋转后的字符串与goal相等,则返回true。如果所有的旋转都不相等,最后返回false。

时间复杂度: O(n^2)

空间复杂度: O(n)

class Solution:
    def rotateString(self, s: str, goal: str) -> bool:
        if s == goal:
           return True  # 直接比较s和goal是否相等
        for i in range(len(s)-1):
            # 生成从i+1到末尾加上开头到i的旋转字符串
            if s[i+1:]+s[:i+1] == goal:
                return True  # 如果旋转后的字符串等于goal,则返回true
        return False  # 如果所有旋转都不匹配,则返回false

Explore

在这个问题中,从位置0开始旋转实际上意味着不进行任何旋转,因为整个字符串会保持不变。这种情况已经在函数的一开始通过`if s == goal`进行了直接比较。因此,从位置1开始旋转是为了避免重复计算这种无变化的情况,直接从可能导致字符串内容改变的第一个旋转开始检查。

使用`range(len(s)-1)`是因为在旋转操作中,当`i`等于字符串的长度减1时,执行`s[i+1:]+s[:i+1]`将得到`s[:len(s)]`,即原字符串本身,这种旋转其实是无效的,相当于没有旋转。因此,实际的有效旋转只需要考虑到字符串长度减1的位置。

这个题解没有明确指出需要检查`s`和`goal`的长度是否相等,但从逻辑上讲,如果两个字符串长度不同,它们是不可能通过旋转变为相等的。因此,在实际应用中应当在比较之前加入长度相等的判断,以避免不必要的计算和可能的错误。

题解中的比较逻辑是基于字符串整体相等性的直接比较,对于重复字符的存在并不会产生影响。因为无论字符串中的字符如何重复,只要通过某种旋转能够使得两个字符串完全相等,该方法都能正确返回结果。因此,重复字符的存在不会影响旋转后字符串比较的逻辑。