对于给定的数组,循环左移p个元素

来源:互联网 发布:linux gateway 设置 编辑:程序博客网 时间:2024/05/18 03:41

/*
问题描述:对于给定的数组,循环左移p个元素
说明:对于这个问题,我想了有三种方法。(当然,还参考了资料),把它们简要的实现出
来了。现简要叙述如下:
MoveLeft1:这种算法的思路是,将第一个元素暂时保存在temp,然后把后面要移动到这个位置的元素放在这个位置,接着再把这个元素后面的元素移动到第二个位置。就这样,一步一步直到最后一个元素。要有一点说明的是,这种算法需要保存一个指针,保存的是正在左移的组是哪一组,为的是有些情况是重复移动的。比如说:1,3,2,5,4,6(移动两个元素)。
说的有点复杂,直接看图:

这里写图片描述

这个算法的时间复杂是O(N),空间复杂度是O(1)

MoveLeft2:第二种方法是我参考王道资料上的。人家想的思路就是比我的要清晰。1,3,2,5,4,6(移动两个元素)。最终的结果是2,5,4,6,1,3。
(1)、我先逆转前两个元素:(3,1,2,5,4,6)。
(2)、再逆转后面的四个元素:(3,1,6,4,5,2)
(3)、再把整个数组逆转一下。即得到(2,5,4,6,1,3)。
牛逼的思路。和我之前说的一种思路差不多,就是以结果推过程。
这种算法的时间复杂度是O(N),空间复杂度为O(1)

MoveLeft3:这个算法的思路最简单。就是把前p个元素先转移出来,然后移动后面的元素。最后再把转移的元素放在后面。
这种算法的时间复杂度是O(N),空间复杂度取决于p即左移的元素个数。

*/

//循环左移1void MoveLeft1(Sqlist &L,int p){    int temp_index = 0,temp_val = L.data[0];    //首先保存第一个元素和下标    int move_cou = 0;   //用来保存已经移动的元素的个数    int i = 0,j = 0;    while(move_cou < L.length)    {        j = (i+p) % L.length;   //要移动到此位置的元素的位置        if(j == temp_index )    //如果和标志指针相同,说明构成了一个循环组,下一次需要从下一组开始        {            L.data[i] = temp_val;            ++temp_index;            temp_val = L.data[temp_index];            i = temp_index;        }        else        {            L.data[i] = L.data[j];            i = j;        }        ++move_cou;    }}
//逆转元素void Reverse(Sqlist &L,int st,int _end){    int temp;    while(st<_end)    {        temp = L.data[st];        L.data[st] = L.data[_end];        L.data[_end] = temp;        ++st;        --_end;    }}//循环左移2void MoveLeft2(Sqlist &L,int p){    p = p%L.length;    Reverse(L,0,p-1);    Reverse(L,p,L.length-1);    Reverse(L,0,L.length-1);}
//循环左移3void MoveLeft3(Sqlist &L,int p){     p = p%L.length;    //将前p的元素暂时保存在temp数组中    int temp[p];    for(int i = 0;i<p;++i)    {        temp[i] = L.data[i];    }    int j = 0;    for(int i = 0;i<L.length;++i)    {        if(i<L.length-p)        //移动后面L.leng-p个元素            L.data[i] = L.data[i+p];        else                        //将temp中的元素放在原数组后面            L.data[i] = temp[j++];    }}
阅读全文
0 0
原创粉丝点击