排列问题算法-next_permutation,康托编码

来源:互联网 发布:cyberghost for mac 编辑:程序博客网 时间:2024/05/02 01:42
#pragma once#include <algorithm>#include <set>using namespace std;class Permutation {public:    /**    1 2 3 4    1 2 4 3    1 3 2 4    1 3 4 2    1 4 2 3    1 4 3 2    **/    vector<int> nextPermutation(vector<int>& cur) {        int endI = cur.size() - 1;        while (endI >= 1 && cur[endI - 1] > cur[endI]) endI -= 1;        if (endI == 0) {            sort(cur.begin(), cur.end());            return cur;        }        int i = cur.size() - 1;        for (; i >= endI; --i) {            if (cur[i] > cur[endI - 1])break;        }        swap(cur[i], cur[endI - 1]);        sort(cur.begin() + endI, cur.end());        return cur;    }        /*        1 2 3 4 ->0        1 2 4 3 ->1        1 3 2 4 ->2        1 3 4 2 ->3        1 4 2 3 ->4        1 4 3 2 ->5        2 ...   ->6        3 ...   ->12        4 ...   ->18        */      int getPermutationNum(int n, vector<int>& data) {        int ans = 0;        set<int> used;        for (int i = data.size() - 1; i >= 0; --i) {            int base = factorial(i);            int fold = getFold(used, data[data.size() - i - 1], n);            used.insert(data[data.size() - i - 1]);            ans += base * fold;        }        return ans;    }    vector<int> kthPermutation(int n, int k) {        vector<int> ans;        int i = n;        set<int> used;        while (i > 0) {            int base = factorial(i - 1);            int remain = k % base;            int cur = k / base;            int ansEle = 0;            ansEle = getNextNum(used, cur, n);            used.insert(ansEle);            ans.push_back(ansEle);            i -= 1;            k = remain;        }        return ans;    }private:    int getFold(set<int>& used, int k, int n) {        int ans = k;        for (int i = 0; i < k - 1; ++i) {            if (used.count(i + 1)) {                ans -= 1;            }        }        return ans - 1;    }    int getNextNum(set<int>& used, int k, int n) {        int j = 0;        for (int i = 0; i < n; ++i) {            if (used.count(i + 1) != 0) continue;            if (j == k) return i + 1;            j++;        }        return 0;    }    int factorial(int n) {        int ans = 1;        for(int i = 1; i<= n; ++i) ans *= i;        return ans;    }};
0 0
原创粉丝点击