设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量。
1.算法复杂度为O(K * N)的方法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void rightShift(char *arry,int n,int k){
while(k--){
char t=arry[n-1];
for(int i=n-1;i>0;i--){
arry[i]=arry[i-1];
}
arry[0]=t;
}
}
int main()
{
char a[]="abcd1234";
rightShift(a,8,4);
for(int i =0;i<8;i++){
printf("%c",a[i]);
}
printf("\n");
return 0;
}
2.三步反转法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Reverse(char* arr, int b, int e) //字符串从b到e反转
{
for(;b<e; b++, e--)
{
char temp = arr[e];
arr[e] = arr[b];
arr[b] = temp;
}
}
void RightShift(char* arr, int N, int K)
{
K %= N;
Reverse(arr,0,N-K-1); //倒数k个之前的字符串反转
Reverse(arr,N-K,N-1); //倒数k个字符反转
Reverse(arr,0,N-1); //整体反转
}
int main()
{
char a[]="abcd1234";
RightShift(a,8,4);
for(int i =0;i<8;i++){
printf("%c",a[i]);
}
printf("\n");
return 0;
}
3.三步反转法之二
#include <stdio.h>
#include <string.h>
char * invert(char *start, char *end)
{
char tmp, *ptmp = start;
while (start != NULL && end != NULL && start < end)
{
tmp = *start;
*start = *end;
*end = tmp;
start ++;
end --;
}
return ptmp;
}
char *right(char *s, int pos) //pos为要旋转的字符个数,或长度,下面主函数测试中,pos=3。改的是向右旋转
{
int len = strlen(s);
invert(s, s + (len-pos - 1)); //倒数pos之前的先反转
invert(s + (len-pos), s + (len - 1)); //倒数pos个反转
invert(s, s + (len - 1)); //整体反转
return s;
}
char *left(char *s, int pos) //pos为要旋转的字符个数,或长度,下面主函数测试中,pos=3。现在是向左旋转
{
int len = strlen(s);
invert(s, s + (pos-1)); //从左边pos个字符先反转
invert(s + pos, s + (len - 1)); //pos个之后的后半段反转
invert(s, s + (len - 1)); //整体反转
return s;
}
int main()
{
char s[] = "abcdefghij";
//puts(left(s, 3));
puts(right(s, 3));
return 0; }