leetcode 189. 旋转数组(Rotate Array)

题目描述:

给定一个数组,将数组中的元素向右移动 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) 的原地算法。

算法:

class Solution {
public:
    void rotate1(vector<int>& nums, int k){
        // method 1
        int sz = nums.size();
        if(k <= sz/2){
            for(int i = 0; i < k; i++){
                // for the i-th step
                int pre = nums[sz-1];
                for(int j = sz - 1; j > 0; j--){
                    nums[j] = nums[j-1];
                }
                nums[0] = pre;
            }
        }else{
            k = sz - k;
            for(int i = 0; i < k; i++){
                // for the i-th step
                int pre = nums[0];
                for(int j = 0; j < sz - 1; j++){
                    nums[j] = nums[j+1];
                }
                nums[sz - 1] = pre;
            }
        }
        
    }
    
    int gcd(int a, int b){
        int c = a;
        while(a % b){
            c = a % b;
            a = b;
            b = c;
        }
        return b;
    }
    
    void rotate2(vector<int>& nums, int k){
        // method 2
        int sz = nums.size();
        int cycle = gcd(sz, k);
        int _sz = sz / cycle;
        for(int i = 0; i < cycle; i++){
            int val = nums[i];
            int idx = i;
            int pre = 0;
            for(int j = 0; j < _sz-1; j++){
                pre = (idx + sz - k)%sz;
                nums[idx] = nums[pre];
                idx = pre;
            }
            nums[idx] = val;
        }
    }
    
    void flip(vector<int>& nums, int start, int end){
        while(start < end){
            swap(nums[start++], nums[end--]);
        }
    }
    
    void rotate3(vector<int>& nums, int k){
        // method 3
        // target: move the last k elements to the front
        // 1. flip the whole vector
        // 2. flip the first k elements
        // 3. flip the rest of elements
        int sz = nums.size();
        flip(nums, 0, sz-1);
        flip(nums, 0, k-1);
        flip(nums, k, sz-1);
    }
    
    void rotate(vector<int>& nums, int k) {
        int sz = nums.size();
        if(sz <= 1){
            return ;
        }else{
            k %= sz;
        }
        if(k == 0){
            return ;
        }
        // rotate1(nums, k);   // time limited
        rotate2(nums, k);   // accept
        // rotate3(nums, k);   // accept
    }
};
posted @ 2019-03-20 14:01  zhanzq1  阅读(338)  评论(0)    收藏  举报