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]
説明:

できるだけ多くの解決策を考えてください。この問題を解決するには、少なくとも3つの異なる方法があります。
スペースの複雑さが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