您的位置:首页 > 编程语言

编程之美 2.17 数组循环移位

2013-01-06 11:10 253 查看
给定N个数组,将其向右循环移动K位。此题在编程珠玑上曾经见过,先写个例子观察:abcdefg,向右移动3位 ->efgabcd。最简单的思路是循环将整个数组移动k位(这里k可以转化为k%=n,因为循环移位整个数组可以看成一个环),但是时间复杂度较高。然后,通过上述例子发现,循环移位后,数组的两个部分仅仅是移动了位置,其它不变,所以,可以用一个临时数组缓存较小的一部分,然后将较大的一部分移动到移位后的位置,再将较小的部分加入。但是,如果数组很大,可能空间复杂度会较大。

第三个方法是通过对两部分分别逆序,再整个逆序达到效果:

1、逆序abcd:abcdefg -> dcbaefg;

2、逆序efg:dcbaefg -> dcbagfe;

3、逆序整个数组: dcbagfe -> efgabcd;

这个算法原理:向右移动k(k%=n)位的效果等同于将数组看作两个部分:(a1,a2...an-k-1)(an-k...an-1),设为mn,现在移位后就成为了nm。则可以通过这样的步骤:mn->m'n'->(m'n')'=nm.之所以采用这种方式就是因为逆序字符串不需要额外的空间,时间复杂度也是线性的。

编程珠玑上还有一个杂技算法,但是要注意循环链的存在,即n和k的设定不同会有多个循环链,链的个数为n和k的最大公约数,证明不知,有兴趣再看吧。

以下为逆序算法:

void Reverse(char *arr, int a, int b){
for (int i = a, j = b; i < j; ++i, --j){
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}

void RightShiftV2(char *arr, int n, int k){
k %= n;
Reverse(arr, 0, n-k-1);
Reverse(arr, n-k, n-1);
Reverse(arr, 0, n-1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: