• 【LeetCode-数组】旋转数组


    题目描述

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

    输入: [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]
    
    输入: [-1,-100,3,99] 和 k = 2
    输出: [3,99,-1,-100]
    解释: 
    向右旋转 1 步: [99,-1,-100,3]
    向右旋转 2 步: [3,99,-1,-100]
    

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

    题目链接: https://leetcode-cn.com/problems/rotate-array/

    思路1

    每次移动一个元素,数组中的元素都移动了一次算一遍,移动 k 遍。在移动的时候,假设要把 nums[i] 移动到 nums[j],则要把 nums[j] 在被覆盖之前保存起来。
    代码如下:

    class Solution {
    public:
        void rotate(vector<int>& nums, int k) {
            if(k==0 || nums.empty() || nums.size()==1) return;
    
            int n = nums.size();
            for(int i=0; i<k; i++){
                int pre = nums[0];
                int cur = 0;
                for(int j=0; j<n; j++){
                    cur = nums[(j+1)%n];
                    nums[(j+1)%n] = pre;
                    pre = cur;
                }
            }
        }
    };
    // 超时
    

    该方法超时。

    • 时间复杂度:O(nk)
    • 空间复杂度:O(1)

    思路2

    使用另一个数组存储旋转后的结果,然后再用旋转后的结果覆盖原数组。

    class Solution {
    public:
        void rotate(vector<int>& nums, int k) {
            if(k==0 || nums.empty() || nums.size()==1) return;
    
            int n = nums.size();
            vector<int> a(n, 0);
            for(int i=0; i<n; i++){
                a[(i+k)%n] = nums[i];
            }
    
            for(int i=0; i<n; i++) nums[i] = a[i];
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

    思路3

    我们发现当我们旋转数组 k 次, k % n 个尾部元素会被移动到头部,剩下的元素会被向后移动。所以可以使用反转:

    • 对整个数组进行反转,范围为 [0, n);
    • 对前 k 个数字进行反转,范围为 [0, k-1];
    • 对后 n-k 个数字进行反转,范围为 [k, n);

    例如:

    假设 n=7 且 k=3 。
    
    原始数组                  : 1 2 3 4 5 6 7
    反转所有数字后             : 7 6 5 4 3 2 1
    反转前 k 个数字后          : 5 6 7 4 3 2 1
    反转后 n-k 个数字后        : 5 6 7 1 2 3 4 --> 结果
    

    代码如下:

    class Solution {
    public:
        void rotate(vector<int>& nums, int k) {
            if(k==0 || nums.empty() || nums.size()==1) return;
    
            int n = nums.size();
            k = k % n;  // 别忘了这一步,因为 k 可能比 n 大
            reverse(nums, 0, n-1);
            reverse(nums, 0, k-1);
            reverse(nums, k, n-1);
        }
    
        void reverse(vector<int>& nums, int left, int right){
            while(left<right){
                swap(nums[left], nums[right]);
                left++;
                right--;
            }
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    参考

    https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode/

  • 相关阅读:
    LCG(linear congruential generator): 一种简单的随机数生成算法
    (转载)STL map与Boost unordered_map的比较
    永远让比较函数对相等的值返回false
    NYOJ 654喜欢玩warcraft的ltl(01背包/常数级优化)
    Java杂记
    流量控制与拥塞控制
    PHP获取当前页面地址
    表单验证实例
    博客几种可选代码配色方案
    $_POST,$_GET,$_REQUEST区分
  • 原文地址:https://www.cnblogs.com/flix/p/13292055.html
Copyright © 2020-2023  润新知