问题描述
给定字符数组“abcdef”, 输入移动位数(默认右侧移动)step,并将新的字符串输入。要求时间复杂度为O(n),空间复杂度O(1)。
方法签名如下:
private static void moveStr3(char[] str,int step);
解决方法
工具类
/**
*
* @param str
* @param step
* @return -1 直接返回
*/
private static int getValidStep(char[] str,int step){
if(str.length==1){
return -1;
}
if(step%str.length==0){
return -1;
}
while(step<0){
step += str.length;
}
while (step>str.length){
step %= str.length;
}
return step;
}
方法一暴力破解法(时间复杂度为O(kN))
/**
* 暴力破解法
* 每次移动n步骤,累计移动k次
* @param str
* @param step
*/
private static void moveStr1(char[] str,int step){
step = getValidStep(str, step);
if(step==-1){
return;
}
for (int stepNum = 1;stepNum <= step;stepNum++){
char last = str[0];
for (int i=1;i<str.length;i++){
str[i - 1] = str[i];
}
str[str.length-1] = last;
}
}
方法二 局部复制法(空间复杂为O(k),时间复杂度为O(n))
/**
* 分块复制 一次for循环
* @param str
* @param step
*/
private static void moveStr2(char[] str,int step){
step = getValidStep(str, step);
if(step==-1){
return;
}
char tmp[] = new char[step];
//a. 将前step个字符复制到tmp数组中
//b. 将前step个字符复制到tmp数组中
//c. 将tmp数组中元素复制会原始数组中
int offset = str.length - step;
for (int i = 0; i < str.length; i++) {
if(i<step){
tmp[i] = str[i];
}
if(i< offset){
str[i] = str[step+i];
}else {
str[i] = tmp[i - offset];
}
}
}
方法三 字符串翻转 (时间复杂度、空间复杂度符合题意)
/**
* 字符串翻转 一次for循环
*
* "abcdef"
* X = abcd X' = dcba
* Y = ef Y' = fe
*
* X'Y' = dcbafe
* (X'Y')' = efabcd
* @param str
* @param step
*/
private static void moveStr3(char[] str,int step){
step = getValidStep(str, step);
if(step==-1){
return;
}
int offset = str.length - step;
for (int i = 0; i < str.length; i++) {
//前半部分翻转
if(i<step/2){
char tmp = str[i];
str[i] = str[step-i-1];
str[step-i-1] = tmp;
}
//后半部分翻转
if(i<offset/2){
char tmp = str[str.length-i-1];
str[str.length-i-1] = str[str.length-i-offset];
str[str.length-i-offset] = tmp;
}
//整体翻转
if(i<str.length/2){
char tmp = str[i];
str[i] = str[str.length-1-i];
str[str.length-1-i] = tmp;
}
}
}