旋转数组-环状替换思路

在循环过程中,从位置0开始进行移动,位置0的元素会放在x=(0 + k) % n的位置上,为了不再次开辟空间,我们在数组上直接进行元素的交换,这样完成了位置0的元素值和位置x的元素值,然后在x位置上进行上述的循环过程,即x1=(x + k) % n,交换x位置和x1位置的元素值,不断进行循环,直到回到初始位置0.

但是,我们容易发现,在回到初始位置0的时候,有可能出现有元素没有被遍历到的情况,这个时候我们应该从下一个元素开始重复上述的循环过程。所以这时候要确定两个条件,一个是确定结束循环的条件,另一个是确定结束整个循环的条件。

确定结束循环的条件比较好理解,当初始位置的索引不等于循环过程中的索引就一直进行本轮的循环,换一句话说当循环过程中的索引等与本轮循环的初始位置的索引时,就停止本轮的循环。

确定结束整个循环的条件需要知道要进行多少轮的循环,我们将从初始位置循环再到初始位置的过程中遍历的所有元素个数设为b,题中给出需要移动的位数为k,数组的长度为n,从初始位置循环再到初始位置这个过程中走过数组的圈数设为a,所以可以知道an=bk。即an一定为n,k的公倍数。因为在每轮的循环过程中,只要回到初始位置我们就停止本轮的循环,所以a的值要求最小,故an就是n,k的最小公倍数bk=an=nk的最小公倍数。所以bk=nk的最小公倍数,所以b=nk的最小公倍数/k,因为b是从初始位置循环再到初始位置的过程中遍历的所有元素个数,n是数组中用元素的个数,故a=n/b -> a=n/nk的最小公倍数=nk/nk的最小公倍数。

以下代码来自力扣方法二

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
       int n = nums.size();
       k = k % n;
       int count = gcd(k, n);
       for(int start = 0; start < count; start++) {
           int current = start;
           int prev = nums[start];
           do {
               int next = (current + k) % n;
               swap(nums[next], prev);
               current = next;
           } while(start != current);
       }
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值