旋转字符串

117 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

一、题目

leetcode 旋转字符串

给定两个字符串, 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 由小写英文字母组成

二、题解

方法一

要使字符串s经过若干次操作变为字符串goal,那么字符串s和字符串goal的长度必定要相等,所以如果这两个字符串不相等可以直接返回false。如果s旋转之后会与goal相等,那么在s中肯定能找到一段子字符串与goal的中前一段子字符串相等,其余的可能需要从 s的前一段子字符串查询。所以我们可以遍历字符串s的字符,首先需要找到s中一个字符与goal的第一个字符相等的位置,如果找不到就返回false,否则就先记录下s中这个字符位置为mark,然后我们用一个p指针来遍历字符串goal,遍历过程中我们将与字符串 s中的mark之后的字符匹配,即s[mark + p] == goal[p]。然后当mark + p超出字符串s的长度时,我们就需要从新到字符串s的第一个字符开始匹配了。最后匹配完发现p指向goal字符串最后位置,说明完全匹配直接返回true,否则需要继续遍历字符串s

方法二

方法一的操作可能不太好理解,方法一其实是逐个字符来匹配,那么可以稍微优化一下,用整个字符串来比较。同样的首先需要判断字符串s和字符串goal的长度,不相等直接返回false。否则我们遍历字符串s找到其中一个字符与字符串goal第一个字符相等的位置i。 然后我们将字符串s中位置i之后的子字符串与i位置之前的子字符串重新拼接上,相当于在字符串s的位置i上就行了翻转得到一个新字符串,然后将其与字符串goal匹配比较,相等直接返回true,否则继续遍历字符串s来进行这个判断操作,遍历完了就是没有匹配上 返回fals。

方法三

通过前面两次比较,可以发现一个骚操作,前提是字符串s不要太长,否则效率不太好。因为字符串s进行旋转的操作就是头部的字符移动到尾部,所以我们可以将字符串s与字符串s进行拼接获得一个两倍s长度的新字符串ss,那么在字符串s的任意次的旋转之后必定 存在于ss的一个子字符串,所以可以直接判断字符串goal是否是ss的一个子字符串,是说明能匹配返回true,否则返回false。

三、代码

方法一 Java代码

class Solution {
    public boolean rotateString(String s, String goal) {
        int len1 = s.length();
        int len2 = goal.length();
        if (len1 != len2) {
            return false;
        }
        int p;
        for (int i = 0; i < len1; i++) {
            p = 0;
            if (s.charAt(i) == goal.charAt(p)) {
                int mark = i;
                // 往后面匹配看看
                while (p < len2 && s.charAt(mark + p) == goal.charAt(p)) {
                    p++;
                    if (mark + p >= len1) {
                        mark = -p;
                    }
                }
                if (p == len2) {
                    return true;
                }
            }
        }
        return false;
    }
}

时间复杂度:O(n^2),需要循环遍历判断两个字符串的字符。

空间复杂度:O(1),只需常数个空间变量。


方法二 Java代码

class Solution {
    public boolean rotateString(String s, String goal) {
        int len1 = s.length();
        int len2 = goal.length();
        if (len1 != len2) {
            return false;
        }
        for (int i = 0; i < len1; i++) {
            if (s.charAt(i) == goal.charAt(0)) {
                String s2 = s.substring(i) + s.substring(0, i);
                if (s2.equals(goal)) {
                    return true;
                }

            }
        }
        return false;
    }
}

时间复杂度:O(n),需要循环遍历一次s字符串(不考虑库函数)。

空间复杂度:O(n),可能会拼接生成多个新字符串。


方法三 Java代码

class Solution {
    public boolean rotateString(String s, String goal) {
        if (s.length() != goal.length()) {
            return false;
        }
        return (s + s).contains(goal);
    }
}

时间复杂度:O(1),(不考虑库函数)。

空间复杂度:O(n),生成一个两倍s的新字符串。