leetcode_189. 轮转数组

leetcode_189. 轮转数组

题目描述:

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [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:

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

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

题解–反转数组

如果把这道题当成简单的模拟器, 那情况就会变得比较复杂, 除非使用额外的空间, 将原数组复制一份, 然后循环执行nums[(i + k) %length], 这也不是不行, 只是稍显笨拙.

其实我们可以换个思路, 将原来的数组轮转其实可以用反转数组来实现

  1. 将数组整体反转
  2. 将数组0~k-1反转
  3. 将数组k~length-1反转

我们来证明一下, 假如我们要将下面这个数组轮转3个位置,

在这里插入图片描述

我们先将整个数组整体反转

在这里插入图片描述

紧接着反转前3个元素

在这里插入图片描述

在然后, 反转剩下的元素

在这里插入图片描述

看, 是不是很神奇, 我们就真的通过这种方式实现了数组轮转.

原理是什么呢

数组轮转本来就可以看作是直接把数组右边的k个元素直接截下来, 然后插到开头的位置, 但是由与我们这是数组, 不是链表, 不能只移动右边的k个而不动其他的,

这时如果我们让整个数组整体反转, 然后再分别反转前k个, 和后面length - k个, 就等效于直接把后面k个元素拆下来, 插到了开头.

Java

class Solution {
    public void rotate(int[] nums, int k) {
        int length = nums.length;
        k = k % length;
        reverse(nums, 0, length -1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, length -1);

    }
    public void reverse(int nums[], int l, int r) {
        while (l < r) {
            nums[l] = nums[l] ^ nums[r] ^ (nums[r] = nums[l]);
            l ++;
            r --;
        }
    }
}

c++

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int length = nums.size();
        k = k % length;
        reverse(nums, 0, length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, length -1);
    }
    void reverse(vector<int>& nums, int l, int r) {
        while ( l < r) {
            //nums[l] = nums[l] ^ nums[r] ^ (nums[r] = nums[l]);
            swap(nums[l], nums[r]);
            l ++;
            r --;
        }
    }
};
上一篇:Jenkins 安装、部署与配置


下一篇:江协科技51单片机学习- p27 I2C AT24C02存储器