LeetCode 补拙笔记 日期:2026.05.25 题目:796. 旋转字符串

LeetCode 补拙笔记

0. 前言

  • 日期:2026.05.25
  • 题目:796. 旋转字符串
  • 难度:简单
  • 标签:字符串、KMP算法

1. 题目理解

问题描述

给定两个字符串 sgoal,判断 s 是否可以通过若干次"将最左边字符移到最右边"的旋转操作,得到 goal

示例

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

输出:true

解释:abcde 旋转两次得到 cdeab
输入:s = "abcde", goal = "abced"

输出:false

解释:无法通过旋转得到目标字符串。

2. 解题思路

核心观察

  • 字符串 s 的所有旋转结果,都可以看作是 s + s 的一个子串。例如 abcde 的所有旋转都包含在 abcdeabcde 中。
  • 解法一:直接用 contains() 判断,简单但效率取决于语言实现。
  • 解法二:使用KMP算法判断子串,时间复杂度为线性级,效率更高。

算法步骤

  1. 检查 sgoal 长度是否相等,不等直接返回 false
  2. s 拼接为 s + s
  3. 判断 goal 是否是 s + s 的子串。

3. 代码实现

java 复制代码
package lc796;

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

4. 代码优化说明

减少冗余分支,优化KMP实现,代码更简洁紧凑:

java 复制代码
public class Solution {
    public boolean rotateString(String s, String goal) {
        if (s.length() != goal.length()) return false;
        return kmp(s + s, goal);
    }

    private boolean kmp(String mainStr, String pattern) {
        int[] next = getNext(pattern);
        int j = 0;
        for (int i = 0; i < mainStr.length(); i++) {
            while (j > 0 && mainStr.charAt(i) != pattern.charAt(j)) {
                j = next[j - 1];
            }
            if (mainStr.charAt(i) == pattern.charAt(j)) {
                j++;
            }
            if (j == pattern.length()) {
                return true;
            }
        }
        return false;
    }

    private int[] getNext(String pattern) {
        int[] next = new int[pattern.length()];
        int j = 0;
        for (int i = 1; i < pattern.length(); i++) {
            while (j > 0 && pattern.charAt(i) != pattern.charAt(j)) {
                j = next[j - 1];
            }
            if (pattern.charAt(i) == pattern.charAt(j)) {
                next[i] = ++j;
            }
        }
        return next;
    }
}

5. 复杂度分析

  • contains()解法

    • 时间复杂度: O ( n ) O(n) O(n)(Java中String.contains底层为优化的暴力或Boyer-Moore算法,平均线性)
    • 空间复杂度: O ( n ) O(n) O(n),拼接字符串的开销。
  • KMP解法

    • 时间复杂度: O ( n ) O(n) O(n),预处理next数组和匹配过程均为线性。
    • 空间复杂度: O ( n ) O(n) O(n),next数组的开销。

6. 总结

  • 核心思路:利用字符串拼接 + 子串匹配,将旋转问题转化为子串问题。
  • 优化后的KMP实现,避免了内置方法的不确定性,保证了线性时间复杂度,是面试中更推荐的写法。
  • 关键技巧:s+s 包含了s的所有旋转状态,这是解决这类问题的经典套路。
相关推荐
致Great4 小时前
Pi 的上下文压缩,到底是怎么工作的?
算法
wp123_15 小时前
硬件元器件笔记|IPX8 防水 Type‑C 母座安费诺 124018802112A 与 TONEVEE TY48086‑24A 分析
c语言·开发语言·笔记
watersink5 小时前
机器学习聚类算法
算法·机器学习·聚类
mifengxing5 小时前
操作系统 文件系统
笔记·操作系统·计算机408
luj_17686 小时前
桥牌思维启示:系统设计的模块化架构
c语言·开发语言·c++·经验分享·算法
无聊的菜鸟7 小时前
TMS320F2806X学习笔记(零)—— C2000、CCS、新建工程
笔记·mcu·c2000·f2806x
饼饼学习空间智能7 小时前
家庭服务机器人训练数据怎么积累?仿真、真实采集与持续学习的技术路线分析
人工智能·算法·机器学习
ljt27249606618 小时前
Compose笔记(八十三)--onVisibilityChanged
笔记
蛋先生DX9 小时前
你瘦不下来但大模型可以:量化原理了解一下
深度学习·算法·llm