LeetCode-189. Rotate Array

description

Given an array, move the elements in the array k positions to the right, where k is a non-negative number.

Example 1:

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

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

Think of as many solutions as possible. There are at least three different ways to solve this problem.
It is required to use an in-place algorithm with a space complexity of O(1).

Source: LeetCode
Link: https://leetcode-cn.com/problems/rotate-array/

Solve

    // 最大公约数,最小公倍数
    template<typename T>
    T gcd(T a, T b) {
        while (a % b != 0) {
            T c = a % b;
            a = b;
            b = c;
        }
        return b;
    }

    template<typename T>
    T lcm(T a, T b) {
        return a * b / gcd(a, b);
    }

    class Solution {
    public:
        // 方法一,原地交换实现原始版,空间复杂度O(N)原始版
        void rotate_1(vector<int> &nums, int k) {
            const int N = nums.size();
            if (N < 2 || (k % N == 0)) {
                // 少于2个元素或者翻转k是元素个数的倍数,不做任何动作
                return;
            }

            int n = gcd(N, k);
            for (int i = 0; i < n; ++i) {
                int start = i;
                int curPos = i;
                int pre = nums[curPos];
                int next = 0;
                do {
                    int nextPos = (curPos + k) % N;
                    next = nums[nextPos];
                    nums[nextPos] = pre;
                    pre = next;
                    curPos = nextPos;
                } while (curPos != start);
            }
        }

        // 方法一优化版,原地交换实现代码优化版,空间复杂度O(N)原始版
        void rotate_2(vector<int> &nums, int k) {
            const int N = nums.size();
            if (N < 2 || (k % N == 0)) {
                // 少于2个元素或者翻转k是元素个数的倍数,不做任何动作
                return;
            }

            int n = gcd(N, k);
            for (int i = 0; i < n; ++i) {
                int prev = nums[i];
                int curPos = i;
                do {
                    int nextPos = (curPos + k) % N;
                    // 通过每次的元素交换,将当前被覆盖的位置(nextPos)元素保存到prev中,待下次交换使用
                    std::swap(nums[nextPos], prev);
                    curPos = nextPos;
                } while (curPos != i);
            }
        }

        // 方法二,采用辅助数组空间
        void rotate_usespace(vector<int> &nums, int k) {
            const int N = nums.size();
            if (N < 2 || (k % N == 0)) {
                // 少于2个元素或者翻转k是元素个数的倍数,不做任何动作
                return;
            }

            vector<int> record(N, 0);
            for (int i = 0; i < N; ++i) {
                int changePos = (i + k) % N;
                record[changePos] = nums[i];
            }
            nums.assign(record.begin(), record.end());
        }

        // 方法三,采用STL算法实现
        void rotate(vector<int> &nums, int k) {
            const int N = nums.size();
            if (N < 2 || (k % N == 0)) {
                // 少于2个元素或者翻转k是元素个数的倍数,不做任何动作
                return;
            }
            k = k % N; // 处理k > N的场景
            std::rotate(nums.begin(), nums.begin() + (N - k), nums.end());
        }
    };

 

Guess you like

Origin blog.csdn.net/u010323563/article/details/112354866