使用环状替换 Leetcode189

使用环状替换 Leetcode189

一、题目

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

示例 1:

输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向右旋转 2 步: [6,7,1,2,3,4,5] 向右旋转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入: [-1,-100,3,99] 和 k = 2 输出: [3,99,-1,-100] 解释: 向右旋转 1 步: [99,-1,-100,3] 向右旋转 2 步: [3,99,-1,-100]

说明:

尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的 原地 算法。

二、题解

思路:类似于让位子,有一个环形的座位,每个人跑到同一方向下距离自己k个位置的位置上,那么那个位置上的人同样需要跑到距离自己k个位置的位置上,直到所有的人都坐到了自己的后来的位置上。

那么在循环让位的过程中,只需要知道前一个人原来的值,保留自己原来的值,用前一个人原来的值覆盖当前的位置,把自己原来的值传给后来的位置,并且对已让位人数计数。

当nums是1,2,3,4,5,6,7 k=3时,

操作过程为:

1,2,3,1,5,6,7 4

1,2,3,1,5,6,4 7

1,2,7,1,5,6,4 3

1,2,7,1,5,3,4 6

1,6,7,1,5,3,4 2

1,6,7,1,2,3,4 5

5,6,7,1,2,3,4 1

这是一次循环刚好所有的数都让位完的情况

当然还有1,2,3,4 5,6 k=2时

1,2,3,4,5,6

这种情况只会奇数让奇数,偶数让偶数,一次循环是不够的

还需要再一次循环

1,2,3,4,5,6

因而在每次循环前要记录循环开头的位置,当循环到原来开头的位置时,说明这条链上所有能让的都已经让了,但是count<len说明当前还有人没有让完,因此需要从开头下一个位置开始再次循环,直到所有人都已让完。

class Solution {

  public void rotate(int[] nums, int k) {

​    int len=nums.length;

​    int begin=0;//每个循环的开头位置

​    int now;//记录当前位置

​    int count=0;//记录当前已让位的人数



​    while(count<len)

​    {

​      //循环替换,每一个数向后挪k位,当k>nums.length时,挪k%nums.length位

​      //当回到循环开头部分时,循环结束,以当前开头的下一个数来开头

​      int temp;

​      now=begin;

​      int pre=nums[begin];



​      do {

​        now = (now + k) % len;

​        count++;// 让位人数增加

​        temp = nums[now];// 保存当前位置原来的值

​        nums[now] = pre;

​        pre = temp;

​      } while (now != begin);

​      begin++;

​    }

  }

}

猜你喜欢

转载自www.cnblogs.com/zhang-qi123/p/12296135.html