题目描述
- 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
- 地址: 牛客链接
题目分析
- 这题用java的API一下子就能做出来,但显然不是面试官想听的。
- 关于左旋操作,java源码中对数组和链表进行了不同的做法:
- 对于数组,知道坐标变换 i -> (n - i + length) % length 的规律,然后利用循环置换的方式,完成左旋操作
- 例如对于[1, 2, 3, 4, 5] 左旋变为 [4, 5, 1, 2, 3],坐标变换公式为 i -> (n - i + length) % length,利用连环怼的方式,便可以完成循环置换。
- 而对于链表,例如 1 -> 2 -> 3 -> 4 -> 5 ,变换为 4 -> 5 -> 1 -> 2 -> 3。可以分为三部分逆序:
- 前半部分逆序 1 -> 2 -> 3 变为 3 -> 2 -> 1
- 后半部分逆序 4 -> 5 变为 5 -> 4
- 整体逆序 3 -> 2 -> 1 -> 5 -> 4,变成4 -> 5 -> 1 -> 2 -> 3
- 对于该题,将字符串转换为字符数组后,同样可以采取上述方法,但看起来,置换要比交换更为简单一些。
经验教训
代码实现
public String LeftRotateString2(String str,int n) {
int length = str.length();
if(str == null || length == 0 || n < 0) {
return "";
}
char[] chs = str.toCharArray();
reverse(chs, 0, n - 1);
reverse(chs, n, chs.length - 1);
reverse(chs, 0, chs.length - 1);
return new String(chs);
}
public void reverse(char[] chs, int begin, int end) {
int i = begin;
int j = end;
while (i < j) {
char temp = chs[i];
chs[i] = chs[j];
chs[j] = temp;
i++;
j--;
}
}
public String LeftRotateString(String str,int n) {
int length = str.length();
if(str == null || length == 0 || n < 0) {
return "";
}
char[] chs = str.toCharArray();
char cur = chs[0];
int i = 0;
while (cur != chs[(i - n + length) % length]) {
char temp = chs[(i - n + length) % length];
chs[(i - n + length) % length] = cur;
cur = temp;
i = (i - n + length) % length;
}
return new String(chs);
}