/*
问题描述:对于给定的数组,循环左移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即左移的元素个数。
*/
//循环左移1
void 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;
}
}
//循环左移2
void 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);
}
//循环左移3
void 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++];
}
}