算法笔记6:轮转数组

题目

给定一个整数数组 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]

题解

方法一:额外数组

这道题的解法很简单。我们只需要将该数组中对应k位置之后的元素复制到新数组的最前位置,再将k位置前的元素复制到新数组的后续位置即可以完成题目要求。看代码:

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> newArr(n);
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i];
        }
        nums.assign(newArr.begin(), newArr.end());
    }
};

首先我们获取该数组的大小n,并且创建一个新的大小为n的数组。我们遍历原数组,将原数组下标为i的元素放置在新数组下标为(i + k)mod n的位置即可。最后调用assign函数将新数组拷贝回原数组中即可。至此,方法一结束。

方法二:数组翻转

数组翻转是一个很巧妙的解决方法。通过一个表格,我们来看看数组反转的原理。

不难看出,对于任意一个符合题意的数组,只需要进行三次翻转,即可获得所求的数组。下面来看看代码:

class Solution {
public:
    void reverse(vector<int>& nums, int start, int end) {
        while (start < end) {
            swap(nums[start], nums[end]);
            start += 1;
            end -= 1;
        }
    }

    void rotate(vector<int>& nums, int k) {
        k %= nums.size();
        reverse(nums, 0, nums.size() - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.size() - 1);
    }
};

这段代码中,我们声明了一个新的函数reverse用于处理整个数组序列的翻转。该函数有三个参数,分别为一个传入数组和需要翻转的部分的首尾序号。在这个函数中,我们使用了一个循环,依次使用swap函数交换两数的位置,向中间靠拢并执行,最终在数组的中间位置停止。

在rotate函数中,我们首先处理k这个参数。如果k过大,意味着我们需要旋转的圈数就会过多,但是旋转具有周期性,我们只需要得到一个相同的结果,并不需要实际真正把数组旋转k圈。这将提高我们的算法性能。通过对k取n的模,我们得到了旋转的最小次数:新的k。再分别调用三次刚刚写好的reverse函数,分别翻转整个数组,k前半部分数组,k后半部分数组,最终得到所求的数组。封装好一个函数能够极大提升代码的复用性,避免了我们后续的冗余和重复工作。至此,方法二也结束了。

写在最后

对于这一道题,其实还有更多的解决方法,需要我们脱离代码和程序的桎梏,发现一定的规律,去解决问题。永远没有最完美最优秀的算法,但是我们有更合适更具针对性的算法。

Breeze Wang

A student majoring in Software Engineering at Central South University has an understanding of software development techniques, software architecture, and is able to use Godot to develop game projects. I am currently in the Game Development Laboratory at Central South University. I have experience participating in Global Game Jam. Loving game development.