左旋转字符串 【微软面试100题 第二十六题】

题目要求:

  定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。

  例如:把字符串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 翻手算法:时间、空间复杂度和代码简单程度综合性价比最高的算法。

  

代码实现:

杂技法:

#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("
");

    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;
    }
}
View Code

块变换法:

#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;
}
View Code

翻手算法:

#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("
");
    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);
}
View Code
原文地址:https://www.cnblogs.com/tractorman/p/4059594.html