题目要求:
定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。
例如:把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转函数。
参考资料:剑指offer第42题、编程珠玑第二章
题目分析:
方法1 临时空间法:将前i个元素先复制到临时空间中,然后将余下的n-i个元素前移i个位置,最后再把临时空间中的元素放到余下的位置。【分析:如果前i个元素数据量很大,那么临时空间将会很消耗。】
方法2 逐步旋转法:定义一个函数(其功能是将整个向量左旋1位),然后重复调用这个函数i次。【分析:这样会很耗时。】
方法3 杂技法:把a[0]放入一个临时元素中,然后把a[i]放到a[0],a[2i]放到a[i],以此类推(前提是ki < n。如果ki > n,则ki对n取余,如果余数不等于a[0],则继续循环,否则结束本次循环);然后把a[1]放到一个临时元素中,进行和a[0]一样的操作;然后...a[m]。其中m的大小是i和n的最大公倍数。
方法4 块变换法:我们将需要旋转的向量x看成是由向量a和b组成的,那么旋转向量x实际上就是将向量ab的两个部分交换为向量ba,这里向量a代表x的前i个元素。那么整体的变换步骤就可以总结如下了(假设a比b短):
1)将b分割为bl和br两个部分,使得br的长度和a的长度一样(等于i)
2)交换a和br,即ablbr转换成了brbla。通过本次变换,序列a就位于它的最终位置了。
3)我们需要集中精力交换b的两个部分了,这个时候就回到了最初的问题上了。
方法5 翻手算法:时间、空间复杂度和代码简单程度综合性价比最高的算法。
代码实现:
杂技法:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <stdio.h>
int Gcd(int n,int i);
void Sort(int a[],int rotate,int len,int gcd);
int main(void)
{
int a[5]={1,2,3,4,5};
int gcd;
gcd = Gcd(5,4);
Sort(a,4,5,gcd);
for(gcd=0; gcd < 5;gcd++)
{
printf("%d",a[gcd]);
}
printf("\n");
return 0;
}
int Gcd(int n,int i)
{
while(i != n)
{
if(i > n)
{
i -= n;
}
else
{
n -= i;
}
}
return i;
}
void Sort(int a[],int rotate,int len,int gcd)
{
int i,temp,next,before;
for (i = 0; i < gcd; i++)
{
temp = a[i];
before = i;
while (1)
{
next = (before + rotate) % len;
if (next == i)
{
break;
}
else
{
a[before] = a[next];
before = next;
}
}
a[before] = temp;
}
}
块变换法:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <stdio.h>
#define MAX 10
char x[MAX] = "abcdefgh";
/* *
aStart : The start index of block a.
bStart : The start index of block b.
length : The size to be swapped.
*/
void swap(int aStart, int bStart, int length)
{
char tmp;
while(length-- > 0)
{
tmp = x[aStart];
x[aStart] = x[bStart];
x[bStart] = tmp;
aStart++;
bStart++;
}
}
void rotate(int rotdist, int n)
{
int i,j;
int p;
/* check rotdist */
if (rotdist == 0 || rotdist == n)
{
return;
}
/* split the array to two block */
i = p = rotdist;
j = n - rotdist;
while (i != j)
{
if (i > j)
{
/* The start of block b never changed
*/
swap(p - i, p, j);
i -= j;
}
else
{
swap(p - i, p+j-i,i);
j -=i;
}
}
/* i == j */
swap(p-i,p,i);
}
int main()
{
rotate(4,8);
printf("%s",x);
return 0;
}
翻手算法:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <stdio.h>
void reverse(int a[],int start,int end);
void TurnHands(int a[],int i,int n);
int main(void)
{
int a[9]={1,2,3,4,5,6,7,8,9};
int i;
TurnHands(a,5,9);
for(i = 0;i < 9;i++)
{
printf("%d",a[i]);
}
printf("\n");
return 0;
}
void reverse(int a[],int start,int end)
{
if(a==NULL)
return;
int i=start,j=end,temp;
for(;i < j;i++,j--)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
void TurnHands(int a[],int i,int n)
{
if(a==NULL)
return;
if(i<=0 || n<=0 || i>n)
return;
reverse(a,0,i-1);
reverse(a,i,n-1);
reverse(a,0,n-1);
}