力扣:旋转数组(c++)

题目:

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

解:

思路:

关键点确定当前元素要去的位置。确定好要去的位置,将该位置上的元素备份(tag = 该位置的元素),然后替换成当前元素。此时被替换的位置变成了当前位置(否则被替换位置上的元素tag数据会丢失),且要进行移动的数为tag,继续进行要去的位置的查找然后替换。直到全部位置都被替换过。因为每个位置有且只有一次被替换,所以遍历总长度或者替换总次数应该=数组长度。

0 -> 3   

3-> 6   

6-> 9  9>7(长度不足,回返)  故6 -> 2

2 ->5

5 ->8  8>7(长度不足,回返)  故5 -> 1

1 ->4

4 ->7  7=7(长度不足,因为从0开始,回返)   故 4 -> 0

全部元素被替换完成。

 

要去的位置 =  当前位置+跨越长度,共有两种情况:

1:要去的位置 <  数组长度

   根据余数的一个特点是 任何一个数除一个比本身大的数,余数为该数本身

   所以:要去的位置 = (当前位置+跨越长度)% (数组长度)

2:要去的位置 >  数组长度

   假设判断位置为 5 的元素要去的位置 5+3 = 8

   1-7已经走过一圈的长度, 但还有一格未走,因为是环形,又回到了初始的位置1上。如图所示在环形上5要走3格,到达的位置也为 1

   故:其余数为 回返之后的位置,该位置为要去的位置

                         

 

特殊情况:当要去的位置 > 数组长度,并且数组长度为跨越长度的倍数时,会导致第一次回返的数值为 0 ,但此时0已经作为起始点移动过,需要手动将要移动的数的位置+1,否则将会一直不能遍历完数组,陷入死循环。

代码:

void rotate(vector<int>& nums, int k) 
{  
    if (nums.size() < 2 || k == 0)
        return;
    int changenumnow = nums[0], changenumnext = nums[0], tag = 0;  
    int j = 0;   //  j 为移动后的位置
    int count = 0;   // 记录移动次数
    if (k >= nums.size())
    {
        k = k % nums.size();
    }
    while (count != nums.size())
    {
        j = (j + k) % nums.size();
        changenumnext = nums[j];
        nums[j] = changenumnow;
        
        count++;
        // 回返的第一个数必为0,第二个为1,以此类推
        // 先判断回返的数 == 0,确定为特殊情况,并将起始位置+1,变成1,此时1也作为起始位置替换过其他元素,再次回返为1 时,操作同==0
        if (j == tag && j != nums.size()-1)   //处理数组长度为步长倍数的情况
        {
            j = j + 1;
            tag = tag + 1;  // 对0 1 2 3... 元素作为起始位置做标记,用来判断是否做过起始位置替换别的元素            
            changenumnext = nums[j];
        }
        changenumnow = changenumnext;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值