力扣刷题:16-煎饼排序(969)

140 阅读1分钟

煎饼排序是指每次只能翻转前N个节点,完成排序的功能,它的难度在于怎么知道每次应该翻转前几个节点,才能以最快的速度完成排序。

有一种办法是:先从最大的节点开始,将它翻转到最前面(翻转此节点所在位置以及之前的节点),然后再翻转此节点到指定位置上(此节点应该在第几个位置上,就翻转前几个节点,这样这个节点就从第一个位置到指定的这个位置了);依次从大到小,每个节点都处理两次,先移到最前面,再移动到指定位置,这样就完成了煎饼排序的功能。

下面是C++语言实现的功能:

class Solution {
private:
    void reversePre(int length, vector<int> &arr, vector<int> &ind) {
        for (int i = 0, j = length; i < j; i++, j--) {
            int t = ind[arr[i] - 1];
            ind[arr[i] - 1] = ind[arr[j] - 1];
            ind[arr[j] - 1] = t;

            t = arr[i];
            arr[i] = arr[j];
            arr[j] = t;
        }
    }
public:
    vector<int> pancakeSort(vector<int>& arr) {
        vector<int> ret;
        vector<int> ind(arr.size());
        for (int i = 0; i < arr.size(); i++) {
            ind[arr[i] - 1] = i;
        }
        for (int i = arr.size() - 1; i >= 0; i--) {
            int curr_max = ind[i]; // 当前最大
            if (curr_max == i) {
                continue;
            }
            // cout << curr_max << endl;
            if (curr_max > 0) {
                ret.push_back(curr_max + 1);
                reversePre(curr_max, arr, ind);
                // cout << ind[0] << ' ' << ind[1] << ' ' << ind[2] << endl;
                // cout << arr[0] << ' ' << arr[1] << ' ' << arr[2] << endl;
            }
            ret.push_back(i + 1);
            reversePre(i, arr, ind);
            // cout << arr[0] << ' ' << arr[1] << ' ' << arr[2] << endl;
        }
        return ret;
    }
};