编程珠玑2章B问题--n元一维向量向左旋转i个位置

来源:互联网 发布:查找客户资料的软件 编辑:程序博客网 时间:2024/05/14 10:37

问题:将一个n元一维向量向左旋转i个位置,要求使用一个n元的中间向量在n步内完成该工作,仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转。

思路:

想法1:移动x[0]到临时变量t,然后移动x[i]至x[0],x[2i]至x[i],以此类推(将x中的所有下标对n取模),直至返回到取x[0]中的元素,此时改为从t取值然后终止过程。以此类推,直至把x[0]至x[i-1]个变量移动。

想法2:问题可以理解为将数组ab转换成ba。从ab开始,首先对a求逆,得到a'b,然后对b求逆,得到a'b',最后整体求逆,得到(b'a')',就是ba。

代码:

想法1

 

#include <stdio.h>#define MAXSIZE 10void print(const int num[]);void move(int num[],int move_num);int gcd(int num,int move_num);/*  打印信息*/void print(const int num[]){    int tmp_index = 0;    printf("(num) : ");    while(tmp_index<MAXSIZE)    {        printf("%d ", num[tmp_index]);        tmp_index++;    }    printf("\n");}/*  向左移动*/void move(int num[],int move_num){    int index = 0;//遍历次数的索引    int times = gcd(MAXSIZE,move_num);//MAXSIZE和move_num的最大公约数,即遍历次数    int tmp_value = 0;//存储当前遍历的第一个值的临时变量,表示t    int tmp_index = 0;//向后移动move_num位的临时变量,表示x[i]中的i    int tmp_index_index = 0;//向后移动k*move_num位的临时变量(k>=1),表示x[i*2]中的i*2    for(index = 0;index< times;index++)//共遍历times次    {        tmp_value = num[index];        tmp_index = index;        while(1)        {            tmp_index_index = tmp_index + move_num;            if(tmp_index_index >= MAXSIZE)//超过最大值,则减去最大值,剩余值表示新的位置                tmp_index_index -= MAXSIZE;            if(tmp_index_index == index)//与当前索引值相同,说明当前一次的遍历结束(否则,就会重复遍历相同位置),再次遍历下一个                break;            num[tmp_index] = num[tmp_index_index];//把x[2*i]的位置移动到x[i]上            tmp_index = tmp_index_index;//探针移动到i*2上        }        num[tmp_index] = tmp_value;//把t值赋予相应的位置        print(num);//打印每次遍历后的数组    }}/*  求最大公约数*/int gcd(int num,int move_num){    return (!move_num)?num:gcd(move_num,num%move_num);}/*  主程序*/int main(){    int num[MAXSIZE] = {0,1,2,3,4,5,6,7,8,9};    int move_num = 0;    char c;    print(num);    //输入向左移动次数(大于0)    printf("Input times for moving left: ");    while(scanf("%d",&move_num) != 1 || move_num <= 0 || move_num >= MAXSIZE)    {        printf("please input times (>0 and <MAXSIZE)!\n");        while((c = getchar()) != '\n' && c != EOF);        printf("Input times for moving left: ");    }    //移动move_num    move(num,move_num);    return 0;}

 

想法1的时间复杂度为O(n),空间复杂度为O(n)

想法2

#include <stdio.h>#define MAXSIZE 10void print(const int num[]);void move(int num[],int move_num);void reverse(int num[],int start_pos,int end_pos);/*  打印信息*/void print(const int num[]){    int tmp_index = 0;    printf("(num) : ");    while(tmp_index<MAXSIZE)    {        printf("%d ", num[tmp_index]);        tmp_index++;    }    printf("\n");}/*  向左移动*/void move(int num[],int move_num){    reverse(num,0,move_num-1);//翻转a,得到a'    reverse(num,move_num,MAXSIZE-1);//翻转b,得到b'    reverse(num,0,MAXSIZE-1);//翻转a'b'}/*  翻转 *  @param *  num[]:数组 *  start_pos:起始位置 *  end_pos:终止位置 */void reverse(int num[],int start_pos,int end_pos){    int tmp_value = 0;    for(;start_pos<end_pos;start_pos++,end_pos--)    {        tmp_value = num[start_pos];        num[start_pos] = num[end_pos];        num[end_pos] = tmp_value;    }    print(num);}/*  主程序 *  问题:将一个n元一维向量向左旋转i个位置,要求使用一个n元的中间向量在n步内完成该工作, *           仅使用数十个额外字节的存储空间,在正比于n的时间内完成向量的旋转。 *  思路:问题可以理解为将数组ab转换成ba。从ab开始,首先对a求逆,得到a'b,然后对b求逆,得到a'b',最后整体求逆,得到(b'a')',就是ba。 */int main(){    int num[MAXSIZE] = {0,1,2,3,4,5,6,7,8,9};    int move_num = 0;    char c;    print(num);    //输入向左移动次数(大于0)    printf("Input times for moving left: ");    while(scanf("%d",&move_num) != 1 || move_num <= 0 || move_num >= MAXSIZE)    {        printf("please input times (>0 and <MAXSIZE)!\n");        while((c = getchar()) != '\n' && c != EOF);        printf("Input times for moving left: ");    }    //移动move_num    move(num,move_num);    return 0;}

想法2的时间复杂度为O(n),空间复杂度为O(n)
原创粉丝点击