看题目:
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例1:
输入: s = "abcdefg", k = 2 输出: "cdefgab"
示例2:
输入: s = "lrloseumgh", k = 6 输出: "umghlrlose"
说明不需要考虑当输入所需旋转字符的个数大于字符串长度时的情况。
三种方法:
3. 与2的思路差不多,但我们自定义反转法(减少空间的浪费)
通过读题,并借鉴一些他人的思路,这里就介绍三种解法:
1. 使用 substring 库函数一行搞定。
先来了解下 substring 这个方法:
通过JDK文档,我们发现这个方法能够根据下标拿到一个字符串的任意一个子串。
上代码:
class Solution {
public String reverseLeftWords(String s, int n) {
//直接用拼接法:
//将需要旋转的字符串拿出来与不需要旋转的部分重新拼接成一个新的字符串。
return s.substring(n)+s.substring(0,n);
}
}
测试结果:
2. 先局部反转,再整体反转。
这个思路比较巧妙,以需要旋转字符的个数为分隔线,将两部分分别逆序一遍,然后拼接起来,最后拼接起来的整体再次逆序,逆序完成的字符串就是旋转n个字符后的字符串。
原理:
步骤:
1. 把 n 当作分界点,将 s 分割成两个字符串。(这里使用 substring)
2. 分别将两个字符串转换为 StringBuilder 类型,然后分别调用 reverse 方法。
3. 将两个逆序完成的字符串拼接起来,总体再次逆序一遍。
4. 将总体逆序完成的字符串转换为 String 类型,并返回该字符串。
具体代码:
class Solution {
public String reverseLeftWords(String s, int n) {
//以n为分界点,分成两个字符串处理
String l = s.substring(0,n);
String r = s.substring(n,s.length());
//前半部分字符串逆序
StringBuilder l1 = new StringBuilder(l);
l1 = l1.reverse();
//后半部分字符串逆序
StringBuilder r1 = new StringBuilder(r);
r1 = r1.reverse();
//两部分拼接在一起
l1.append(r1);
//拼接后的字符串再次整体逆序
l1 = l1.reverse();
//用String类型返回结果
return new String(l1);
}
}
测试结果:
3. 与2的思路差不多,但我们自定义反转法(减少空间的浪费)
原理:
该方法使用while循环每次交换一组字符,当循环完成后整个字符串就反转完成。
具体代码:
class Solution {
/**
* 自定义反转方法。
*/
public void reverseString(StringBuilder str, int start, int end){
while(start < end){
//备份一下start指向的字符
char ret = str.charAt(start);
//交换字符
str.setCharAt(start, str.charAt(end));
str.setCharAt(end, ret);
//下一组字符
start++;
end--;
}
}
public String reverseLeftWords(String s, int n) {
StringBuilder str = new StringBuilder(s);
//反转前部分
reverseString(str,0,n-1);
//反转后半部分
reverseString(str,n,s.length()-1);
//整体反转一遍
reverseString(str,0,s.length()-1);
return new String(str);
}
}
测试结果:
总结:
虽然办法有许多,但我们要知道什么样的办法适用于什么样的场景。而反转法也是我们需要掌握的。在leetcode上除了这道题,也还有许多的反转字符串题目,有兴趣的可以使用反转法去尝试一下。