LeetCode - 189. 旋转数组

描述

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotate-array/

求解

    // 最大公约数,最小公倍数
    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());
        }
    };

猜你喜欢

转载自blog.csdn.net/u010323563/article/details/112354866
今日推荐