题目描述

✅ 剑指 Offer 58 - II. 左旋转字符串

image-20261001230752588

题意分析

将字符串开头的 n 个字符整体移到末尾,前缀和剩余后缀各自的内部顺序不变,返回旋转后的字符串。

解法:字符串切分

核心思路

[!blue]

设字符串长度为 L,把原串写成 A + B,其中 A 是要移走的前缀,B 是剩下的后缀。移走 A 后,B 自然排到最前,再把 A 接到末尾,结果就是 B + A,不需要逐次移动字符。

代码用 k = n % L 表示有效偏移,因为左旋一整圈又回到原串;题目保证 1 <= n < L,所以合法输入下 k 就是 n。切分点为 k,前缀取半开区间 [0, k),后缀取 [k, L),两段恰好覆盖原串且不重叠。

解题步骤

  1. 确定有效偏移 k = n % L,Java 中直接用变量 n 保存它。
  2. 取从下标 k 到末尾的后缀,再取前 k 个字符作为前缀。
  3. 按后缀、前缀的顺序拼接并返回。

代码实现

class Solution {
    public String reverseLeftWords(String s, int n) {
        int len = s.length();

        n %= len;

        // 后缀放在前面,原来的前 n 个字符整体移到末尾。
        return s.substring(n) + s.substring(0, n);
    }
}
func reverseLeftWords(s string, n int) string {
    if len(s) == 0 {
        return s
    }
    k := n % len(s)

    // 后缀放在前面,原来的前 n 个字符整体移到末尾。
    return s[k:] + s[:k]
}

复杂度分析

  • 时间复杂度:$O(L)$,其中 L 为字符串长度;拼接结果需要复制 L 个字符单位。
  • 空间复杂度:$O(L)$,用于返回的新字符串;Java 截取子串还需 $O(L)$ 临时空间,Go 的两段切片为视图。

关键点总结

[!green]

  • 切分点 k 是未被移动部分的第一个下标,前缀长度正好为 k。
  • 拼接后长度及每个字符的出现次数不变。

易错点总结

[!yellow]

  • 把前缀再接后缀只会得到原串。
  • 子串右端点不包含在内,前缀应截取到 k,不是 k - 1。
  • 整体反转会改变段内顺序,不是左旋转。

相似题目

题目 难度 关联与区别
189. 轮转数组 中等 循环平移可用取模与分段反转,本题向左旋转字符,原题向右旋转数组,方向需对应。
796. 旋转字符串 简单 原题判断是否存在某次旋转可匹配,本题给定偏移量并返回实际旋转结果。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2020/76497124
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!