问题描述:将一个具有n个元素的字符串向左循环移动i个位置。例如,假设n=8,i=3,那么字符串abcdefgh移动之后变成defghabc.
对于整数数组1,2,3,4,5,6,7,8,9,10循环向左移动5位的结果为6 7 8 9 10 1 2 3 4 5.
条件: 时间复杂度O(n), 空间复杂度O( 1 ).
人们可能想到的解法:
一:先将数组或字符串中的前i个元素复制到一个临时数组中,接着将余下的n-i个元素左移i个位置,然后再将前i个元素从临时数组中复制到数组中后面的位置。这个方案使用了i个额外的位置,浪费了空间。
二:定义一个函数来将x向左旋转一个位置,然后调用该函数i次,但是这种方法太浪费时间。时间与n成比例
最简单和最有效的方法如下(分块旋转和整体旋转):
将一个具有10个元素的数组(1 2 3 4 5 6 7 8 9 10)想左循环移动5个位置,采用摇手的方法:
先是掌心对着自己,左手在右手的上面,如下图所示:
实现代码如下:
#include<stdio.h>
void reverse(int a[],int start,int end ) //转数组a中start到end之间的元素
{
int temp=0;
int i=start;
int j=end;
while(i<=j)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
i++;
j--;
}
}
void show(int a[],int len)
{
for(int i=0;i<len;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
void main()
{
int a[]={1,2,3,4,5,6,7,8,9,10};
int len=sizeof(a)/sizeof(int);
show(a,len);
int steps=5;//循环向左移动的位数
reverse(a,0,steps-1);
show(a,len);
reverse(a,steps,len-1);
show(a,len);
reverse(a,0,len-1);
show(a,len);
}
对于字符串的翻转可以采用strcpy或memcpy函数来实现,下面该题在许多公司笔试题里面出现过。
如:
void loopmove(char *pStr,int steps)
{
int n=strlen(pStr)-steps;
char temp[100];
strcpy(temp,pStr+n);
strcpy(temp+steps,pStr);
*(temp+strlen(pStr))='\0';
strcpy(pStr,temp);
}