《剑指offer》之字符串旋转问题

最近做了几道字符串旋转的问题,发现其解决思路是一样的,于是写此文小结一下。

1、左旋转字符串

力扣链接

题目描述

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcXYZdef"和数字3,该函数将返回左旋转两位得到的结果"XYZdefabc"。

解题思路

这道题当然可以用简单的substring方法直接得结果,但是这应该不是算法出题者的本意。

解这种题常用的思路是多次翻转,我们要知道 BA = 旋转(旋转(A)旋转(B))
意思也就是 按题意分割的部分先旋转,再将整体旋转,最后就是所得的结果。
若还不懂可以看下图说明:
在这里插入图片描述在这里插入图片描述
明白了实现思路在写代码就容易了。

package String;

/**
 * @description: 左旋转字符串
 * Input:
 * S="abcXYZdef"
 * K=3
 *
 * Output:
 * "XYZdefabc"
 * @author: Kevin
 * @createDate: 2020/2/23
 * @version: 1.0
 */
public class LeftRotateString {
    public static void main(String[] args) {
        String str = "abcXYZdef";
        int n = 3;
        LeftRotateString solution = new LeftRotateString();
        String res = solution.LeftRotateString(str, n);
        System.out.println(res); // XYZdefabc
    }

    public String LeftRotateString(String str, int n) {
        if (n >= str.length())
            return str;
        char[] chars = str.toCharArray();
        reverse(chars, 0, n - 1);
        reverse(chars, n, chars.length - 1);
        reverse(chars, 0, chars.length - 1);
        return new String(chars);
    }

    private void reverse(char[] chars, int i, int j) {
        while (i < j)
            swap(chars, i++, j--);
    }

    private void swap(char[] chars, int i, int j) {
        char t = chars[i];
        chars[i] = chars[j];
        chars[j] = t;
    }

}

2、右旋转字符串(没这道题,自己举的hh)

要学会举一反三,有左旋同样可以实现右旋。

package String;

/**
 * @description: 自举:右旋转字符串
 *  * Input:
 *  * S="abcXYZdef"
 *  * K=3
 *  *
 *  * Output:
 *  * "defabcXYZ"
 * @author: Kevin
 * @createDate: 2020/2/23
 * @version: 1.0
 */
public class RightRotateString {
    public static void main(String[] args) {
        String str = "abcXYZdef";
        int n = 3;
        RightRotateString solution = new RightRotateString();
        String res = solution.RightRotateString(str, n);
        System.out.println(res); // defabcXYZ
    }

    public String RightRotateString(String str, int n) {
        if (n >= str.length())
            return str;
        char[] chars = str.toCharArray();
        int l = chars.length;
        // 区别就是选择的起始位置
        reverse(chars, l - n, l - 1);
        reverse(chars, 0, l - n - 1);
        reverse(chars, 0, l - 1);
        return new String(chars);
    }

    private void reverse(char[] chars, int i, int j) {
        while (i < j)
            swap(chars, i++, j--);
    }

    private void swap(char[] chars, int i, int j) {
        char t = chars[i];
        chars[i] = chars[j];
        chars[j] = t;
    }

}

3、翻转单词顺序列

题目描述

力扣链接
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。

解题思路

同样是多次旋转,只不过是分割的条件不在是上题中的n,而是成了判断单词。

package String;

/**
 * @description: 翻转单词顺序列
 * @author: Kevin
 * @createDate: 2020/2/24
 * @version: 1.0
 */
public class ReverseSentence {

    public static void main(String[] args) {
        ReverseSentence solution = new ReverseSentence();
        String str = "I am a student.";
        System.out.println(solution.ReverseSentence(str));  // student. a am I
    }

    public String ReverseSentence(String str){
        int n = str.length();
        char[] chars = str.toCharArray();
        int i=0,j=0;
        while (j <= n) {
        	// 空格分割单词,或者为最后一个词
            if (chars[j]==' ' || j==n){
                reverse(chars, i, j-1);
                i = j+1;
            }
            j++;
        }
        reverse(chars, 0, n - 1);
        return new String(chars);
    }

    /**
     * 翻转字符串
     * @param chars 待翻转字符串
     * @param s 起点
     * @param e 终点
     */
    private void reverse(char[] chars,int s,int e){
        while(s<e){
            swap(chars, s++, e--);
        }
    }

    private void swap(char[] chars,int s,int e){
        char t = chars[s];
        chars[s] = chars[e];
        chars[e] = t;
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值