剑指offer-43、左旋转字符串

题⽬描述

汇编语⾔中有⼀种移位指令叫做循环左移( ROL ),现在有个简单的任务,就是⽤字符串模拟这个指令的运算结果。对于⼀个给定的字符序列 S ,请你把其循环左移 K 位后的序列输出。例如,字符序列S="abcXYZdef" ,要求输出循环左移3位后的结果,即" XYZdefabc "。是不是很简单?OK,搞定它!

思路及解答

这道题⽬的意思就是将前⾯ n 位,移动到后⾯,那么我们可以直接从第 n+1 位开始,遍历到最后⼀个,再拼接上前⾯ n 个。

暴力移位

通过k次单步左移实现循环左移。将第一个字符保存,其余字符前移,最后字符放到末尾

java 复制代码
public class Solution {

    public String leftRotateString(String str, int n) {
        if (str == null || str.length() == 0 || n <= 0) {
            return str;
        }
        
        char[] chars = str.toCharArray();
        int len = chars.length;
        n %= len; // 处理n大于字符串长度的情况
        
        // 执行n次单步左移
        for (int k = 0; k < n; k++) {
            // 单步左移:保存首字符,其余前移,最后放回首字符
            char firstChar = chars[0];
            for (int i = 0; i < len - 1; i++) {
                chars[i] = chars[i + 1];
            }
            chars[len - 1] = firstChar;
        }
        
        return new String(chars);
    }
}
  • 时间复杂度:O(k×n),其中k为移动次数,n为字符串长度
  • 空间复杂度:O(1),只使用固定额外空间

字符串切片法(推荐)

值得注意的是, n 可能⼤于 str 的⻓度,那么这种情况下我们应该先对 str 的⻓度取余,保持严谨。即是: n = n % str.length(); 。

java 复制代码
public class Solution {

	public String LeftRotateString(String str, int n) {
		if (str == null || str.length() == 0 || n <= 0) {
            return str;
        }
		String ret = "";
		n = n % str.length();
		for (int i = n; i < str.length(); ++i) {
			ret += str.charAt(i);
		}
		
		for (int i = 0; i < n; ++i) {
			ret += str.charAt(i);
		}
		return ret;
	}

}
  • 时间复杂度 O(n)
  • 空间复杂度 O(n) 。

或者可以用substring 的API

java 复制代码
public class Solution {
    public String leftRotateString(String str, int n) {
        if (str == null || str.length() == 0 || n <= 0) {
            return str;
        }
        
        int len = str.length();
        n %= len; // 处理n大于字符串长度的情况
        
        // 直接截取并拼接:后部分 + 前部分
        return str.substring(n) + str.substring(0, n);
    }
}
  • 时间复杂度:O(n),substring操作需要线性时间
  • 空间复杂度:O(n),创建新的字符串对象

三次反转(数学优美)

利用数学规律:BA = (A'B')',通过三次反转实现循环左移。

分别反转前n位、剩余部分,最后整体反转

java 复制代码
public class Solution {

    public String leftRotateString(String str, int n) {
        if (str == null || str.length() == 0 || n <= 0) {
            return str;
        }
        
        char[] chars = str.toCharArray();
        int len = chars.length;
        n %= len;
        
        if (n == 0) return str; // 移动0位直接返回
        
        // 第一步:反转前n个字符
        reverse(chars, 0, n - 1);
        // 第二步:反转剩余字符
        reverse(chars, n, len - 1);
        // 第三步:整体反转
        reverse(chars, 0, len - 1);
        
        return new String(chars);
    }
    
    /**
     * 反转字符数组中指定范围的字符
     * @param chars 字符数组
     * @param start 起始索引
     * @param end 结束索引
     */
    private void reverse(char[] chars, int start, int end) {
        while (start < end) {
            // 交换首尾字符
            char temp = chars[start];
            chars[start] = chars[end];
            chars[end] = temp;
            start++;
            end--;
        }
    }
}
  • 时间复杂度:O(n),每个字符被访问两次
  • 空间复杂度:O(1),原地操作,只使用常数空间
相关推荐
青山木4 分钟前
RocketMQ 入门到原理(三):消息存储原理
java·后端·中间件·架构·rocketmq
MayBaymax5 分钟前
Spring AI Alibaba Graph 实战:客服工单智能处理
java·ai·ai编程
光依旧36 分钟前
MCP实战手记系列(五):让工具返回一个能点的界面(文末附github源码链接)
java·spring ai·前端集成·mcp·mcp apps
APIshop41 分钟前
淘宝选品接口实战:从召回、详情、佣金到转链的 Java 接入笔记
java
泡茶喝茶写代码1 小时前
量化数据进阶:多维实战篇(第 11 篇):历史涨跌停价:涨跌停序列与止损线测算
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
景熙55231 小时前
单体项目编写思路和落地形式
java·开发语言
Ivanqhz1 小时前
Slope One 算法详解:与矩阵分解、共现矩阵的异同
java·服务器·网络·人工智能·深度学习
Bs_MoneyMagnet2 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
万物智能2 小时前
波形发生AD9833模块配置—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
java
计算机毕设定制辅导-无忧学长2 小时前
《基于SpringBoot的未成年人健康知识科普平台的设计与实现》
java·开发语言·vue.js·spring boot·未成年人健康知识科普平台