LeetCode.Rotate Array 旋转数组

本文探讨了在不使用额外空间(O(1))下,如何有效地旋转数组至右方k步,提供了三种不同方法的详细解析及C++、Python代码实现,包括利用STL函数、数组反转以及两两交换元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array, rotate the array to the right by k steps, where k is non-negative.

Example 1:

Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]

Example 2:

Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]

Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
Could you do it in-place with O(1) extra space?

这题有多种解法,其中时间复杂度O(n2)和空间复杂度O(n)的就不讲了,比较简单。我想讲的是时间复杂度O(n)和空间复杂度O(1)的解法。

解法1:
最简单的是直接使用STL函数rotate(beg, newBeg, end)。

C++代码如下:

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k %= n;
        std::rotate(nums.begin(), nums.begin()+n-k, nums.end());
    }
};

解法2:
比上面稍微复杂点,需要3步。
第1步,将前n-k个元素反转次序,为了省事我还是使用STL的函数reverse(beg, end)来实现反转;
第2步,将剩下k个元素反转次序;
最后一步,对整个数组反转次序。这样就可以得到我们需要的结果了。
如下所示:
输入:[1,2,3,4,5,6,7] and k = 3
第1步: [4,3,2,1,5,6,7]
第2步:[4,3,2,1,7,6,5]
第3步:[5,6,7,1,2,3,4]

C++代码如下:

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k %= n;
        reverse(nums.begin(), nums.begin()+n-k);
        reverse(nums.begin()+n-k, nums.end());
        reverse(nums.begin(), nums.end());
    }
};

解法3:
上面两种方法都比较好理解,一看就知道怎么回事。这第3种方法通过两两交换来实现我想了好长时间,直觉感觉两两交换肯定可以实现,但就是当剩余的没交换长度小于k以后就不知道该怎么处理了。当时就卡在这里,不知如何进行。现在我们来想一下,假如k等于数组长度,那么结果会怎样?我们发现经过旋转数组回到了最初状态,没有变化,刚好旋转了一个周期。由此,我们可以想到如果k大于数组的长度,其实旋转的只是k减去数组长度以后多余的部分,也就是说我们需要旋转的只是k%nums.size()部分,这样就全弄懂了。我们通过两两交换先将k%nums.size()个元素完成交换,然后去掉已经交换的部分,剩下的部分继续通过两两交换将k%n个元素完成交换,直到n为0。
过程如下所示:
输入:[1,2,3,4,5,6,7] and k = 3
首先,第1个元素和第n-k个元素交换,即:1和5,2和6,3和7分别交换,得到[5,6,7,4,1,2,3],去掉已经完成交换元素可以得到[4,1,2,3],剩下数组长度n = nums.size() - k,k = k%n。
然后,继续将剩下数组的第1个和第n-k个元素交换,即:4和1,4和2,4和3分别交换,得到[1,2,3,4],剩下数组长度n=n-k=1,k=k%n=0,完成交换。

C++代码如下:

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

Python的实现我就直接使用切片大法,切片是个好东西。对数组的操作Python真是比C++方便太多了。

Python代码如下:

class Solution:
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        n = len(nums);
        k %= n
        nums[:] = nums[n-k:] + nums[:n-k]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值