力扣【字符串专题】👊 796. 旋转字符串

708 阅读1分钟

theme: hydrogen

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

题目链接

796. 旋转字符串 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

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

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

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

测试用例

示例 1:

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

限制

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

题目分析

由题目的描述可以确认,所谓的旋转操作,就是将字符串 s 的最左边的字符,移动 到最右侧而已

那最直接的操作,就是将 s 分割为单个字符的数组 arr。通过 shift() 弹出数组的第一个元素,然后通过 push() 将弹出的元素插入到 arr 的最后。在需要比较的时候,通过 join() 将数组元素合并为字符,然后判断是否相等;为了避免上述操作陷入死循环,引入一个额外的标记 n=s.length 表示最多操作数组长度的次数后,即可尝试完 arr 所有的可能的组合放方式

代码实现

这是一个暴力的解法,算法中有大量的数组操作和字符拼接操作,执行耗时性能堪忧

var rotateString = function(s, goal) {
    let arr = s.split(''),
        n = s.length;
    while (n-- > 0) {
        arr.push(arr.shift());
        if(arr.join('')==goal){
            return true;
        }
    }
    return false;
};

image.png

优化

仔细思考,可以发现,所有的组合的方式,很像一个环形队列,每一种组合对应队列中的不同的起点

那么,我们可以将 s 重复一次,即 s1 = s + s,这样,一个环形的队列就变成了单向队列,我们只需要在 s1 以定长的窗口,从头滑到末尾,判断是否存在与 goal 相等的字符即可

这种思路就省去了数组操作和字符拼接操作

var rotateString = function(s, goal) {
    if(s.length!=goal.length)return false;
    s +=s;
    return s.indexOf(goal)>-1;
};

image.png