力扣-旋转数组-关于环状替换理解

力扣-旋转数组-关于环状替换理解

题目链接

题目

个人理解

首先比较难理解的是an=bk

首先你可以把数组想象成一个圆桌,每个人需要走到正确的位置,使得数组满足要求。

而这个等式就是为了计算他们走的路程

首先假设解决n=5,k=2的问题。

  1. an:

相当于1先去2的位置,发现不是自己的位置,继续走一步,发现3就是需要的位置,就停下来了,3站起来找自己应该在的位置,过程跟1一样。因为要求的最后是回到起点,所以他们走的路程是圈的整数倍(你都一步一步走了,怎么可能还不是n的整数倍),且每个位置显然不会被多次访问(哪有换好了,你还去要别人对的位置)。所以这样走的路程是an

  1. bk

相当于这次不一个个问了,它直接多走一步,去到目的地,那么每个元素走k步,遍历了b个元素,走了bk步。

两种的路程你肯定要满足路程一样,所以an=bk。

所以an为n和k的倍数,既然不会重复访问一个元素,那肯定你的整个an都是最小的(多了就冗余了),所以an=lcm(n,k)。

你每次访问的元素个数 b = l c m ( n , k ) k \large b=\frac{lcm(n,k)}{k} b=klcm(n,k),你不会重复访问,所以循环次数可以求出为 n b = n k l c m ( n , k ) = g c d ( n , k ) \large \frac{n}{b}=\frac{nk}{lcm(n,k)}=gcd(n,k) bn=lcm(n,k)nk=gcd(n,k).即n和k的最大公倍数。

同时停止这一圈即你又返回了开始的位置

如果你还是不太明白,你可以试着画出n=5,k=2以及n=6,k=2,(一个五边形,一个六边形),前一个只需要一圈,后一个需要2圈

力扣官方源码
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k = k % n;
        if(k<0){
            return;
        }
        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);
        }      
    }
};
参考
  1. 力扣题解(https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode-solution-nipk/)

  2. https://www.jianshu.com/p/569aab1d7c36

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值