lintCode题目:给定一个字符串和一个偏移量,根据偏移量(之前还把这个理解成了旋转点位置...)原地旋转字符串(从左到右)。
以我小白中的小白的思想,只能浅薄的使用多个for循环去切开这个字符串旋转。
1.先判断这个偏移量是否为0,和字符串的长度是否大于0,确认这个字符串是否需要旋转;
2.计算出实际字符串长度内的偏移量和旋转位置;
3.使用一个临时变量存储,偏移量位置之后的字符放在前面;
4.将字符串偏移量位置之前的字符串放在这个临时变量之后;
5.这样就存起来啦。
public void rotateString(char[] str, int offset) {
// write your code here
int len = str.length;
if(offset == 0 || len==0){
return;
}
offset = offset%len;
char[] temp = new char[len];
int x=0;
for (int i=len-offset; i<len; i++){
temp[x] = str[i];
x++;
}
for (int i=0; i<len-offset; i++){
temp[x] = str[i];
x++;
}
for(int i=0; i<temp.length; i++){
str[i] = temp[i];
}
}
不过我虽然小白但也认为这样的代码非常烂而且没有效率可言......需要一个变量一个字符数组用完就废弃了。
然后就去看了下大家的解法,看到个时间复杂度为O(n)的算法,使用的是多次翻转的方式,很神奇的就旋转了......
public void rotateString(char[] str, int offset) {
// write your code here
int len = str.length;
if(offset == 0 || len==0){
return;
}
offset = offset%len;
reverse(str, 0, len-offset-1);
reverse(str, len-offset, len-1);
reverse(str, 0, len-1);
}
public void reverse(char[] str, int start, int end){
for(int i=start, j=end; i<j; i++, j--){
char temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
看完之后豁然开朗,当需要字符串按偏移量旋转的时候不就是需要将偏移位置之前的字符和偏移位置之后的字符交换下前后位置吗。其实如果先整个翻转下确保两段字符是前后顺序是对的,再分别对两段字符翻转,这样就好理解一些了。
1.确定在这个字符数组中真正偏移量;
2.将偏移位置两侧的字符前后顺序交换,采用直接翻转整个字符串的方式;
3.这时候原地旋转已经做到了,但是旋转两段的顺序是需要和原来顺序一致的,这时候就再分别对两段字符数组进行翻转回原来的顺序;
4.这时候就旋转完啦。
这样做的话只需要个临时变量就行,不过对于复杂度来说我这方面还是不熟,有些具体的好处还是需要多学习讲出一二。
对于这个算法题,我目前还是只在理解阶段,只能说记下了这种类型,对于扩展运用还是需要继续努力的,加油!