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

本文介绍了三种实现数组循环左移的方法:通过构建循环组逐个移动元素、利用数组逆转技巧和借助临时数组辅助。每种方法都详细阐述了其实现步骤,并分析了时间与空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
问题描述:对于给定的数组,循环左移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++];

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值