题目描述
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
思路
这题首先想到的就是用两个字符数组,第一个存取S的前n位,然后后面前移,最后再把存取的数组的n位放回去,即下面这种解法:
public class Solution {
public String LeftRotateString(String str,int n) {
char [] stringArr = str.toCharArray(); // 转换为字符数组
if(stringArr.length<n)
return "";
char [] strNew = new char[n];
for(int i=0;i<n;i++)
strNew[i] = stringArr[i];
int j=0;
for(int i=0;i<stringArr.length;i++){
if(i>stringArr.length-n-1){
stringArr[i] = strNew[j];
j++;
}else{
stringArr[i] = stringArr[i+n];
}
}
String strRead = new String(stringArr);
return strRead;
}
}
后来想到了,转置的公式,即YX = (XTY T)T,T的意思就是转置。即本来是 A数组,然后看成两部分XY,如果想求YX的话,就分别对X逆转,Y逆转,再对XY分别逆转后的结果再做一个总体的逆转,所以有:
public class LeftRotateStringSolution {
public String LeftRotateString(String str, int n) {
char[] chars = str.toCharArray();
if (chars.length < n) {
return "";
}
reverse(chars, 0, n - 1);
reverse(chars, n, chars.length - 1);
reverse(chars, 0, chars.length - 1);
return new String(chars);
}
public void reverse(char[] chars, int start, int end) {
while (start < end) {
char temp = chars[start];
chars[start] = chars[end];
chars[end] = temp;
start++;
end--;
}
}
}
因为String不可变,所以三次反转 怎么都会用额外空间,看到了别人直接用StringBuilder的解法:
public String LeftRotateString(String str,int n) {
if (str == null || n < 0 || n > str.length()) return "";
StringBuilder sb = new StringBuilder(str);
sb.append(sb.substring(0, n)); // 添加0-n的子集
return sb.substring(n, sb.length()); // 输出从n开始到末尾的子集,相当于左旋转了
}
后来一想,既然这里用到了子集的概念,String本身其实也有这个函数,于是可以用String直接做:
public class Solution {
public String LeftRotateString(String str,int n) {
//保证旋转的位数大于字符串的长度,否则返回空字符串
if(n>str.length())
return "";
//把原字符串截取成俩字符串,然后拼接
String s1 = str.substring(0, n);
String s2 = str.substring(n,str.length());
return s2 + s1;
}
}