编程珠玑(二)字符串左旋

编程珠玑第二章的内容,有些内容没有看明白作者的意思。下面是向量左旋和变位词的问题。

一、将一个n元向量左旋转i个位置。例如当N=8,i=3时,向量abcdefgh旋转为defghabc。
这个题目编程之美也有2.17节数组的循环移位和3.1节字符串移位包含的问题。总结下,大概有5种解法,但是编程珠玑上有两种不是很明白,简单介绍下三种算法。

第一种算法比较直接,可以写一个每次都向左移动一位,移动3次即可完成,算法复杂度为i*N。这里还有一个误区,往往会认为i<N其实,并不一定,也可能会有i>>N的情况,这个时候,可以注意到当循环移动N次后向量还原成原来的样子,所以可以先对i=i%N,这样的话i就不会很大,算法复杂度为O(N2)。

第二种算法可以利用空间换时间的方法。也是先对i处理i=i%N,然后开辟一个i大小的空间,保存字符串前i个值。然后直接对把字符串从第i位向前移动i位,然后把空间i个字符补充在后面即可。

第三种算法是通过反转,可以把字符串分为ab两个字串,对a反转~a,对b反转得到~b,ab变为~a~b然后对~a~b整体反转,即可得到ba。此算法还可以针对有些要求,例如要求对abc字符串中c串和a串调换位置,即可对a、b、c串分别进行反转然后整体反转即可。这样时间复杂度只与N有关系为O(N)。下面是三种算法的代码。

#include <iostream>
using namespace std;

void leftShift1(char *a, int len, int i);
void leftShift2(char *a, int len, int i);
void leftShift3(char *a, int len, int i);
void reverse(char *a, int s, int e);

int main()
{
        char a[] = "abcdefgh";
        leftShift3(a, 8, 3);
        printf("%s\n", a);
        return 0;
}

void leftShift1(char *a, int len, int i)
{
        i=i%len;
        while(i--)
        {
                char temp = a[0];
                for(int j=0; j<len; j++)
                        a[j] = a[j+1];
                a[len-1] = temp;
        }
}

void leftShift2(char *a, int len, int i)
{
        char *temp = new char[i]();
        memcpy(temp, a, i);
        memcpy(a, &a[i], len-i);
        memcpy(&a[len-i], temp, i);
}


void leftShift3(char *a, int len, int i)
{
        reverse(a, 0, i-1);
        reverse(a, i, len-1);
        reverse(a, 0, len-1);
}
void reverse(char *a, int s, int e)
{
        while(s<e)
        {
                char temp = a[s];
                a[s] = a[e];
                a[e] = temp;
                s++;
                e--;
        }
}


 

你可能感兴趣的:(编程,c,算法,n2)