permutation sequence

来源:互联网 发布:matlab里矩阵的条件数 编辑:程序博客网 时间:2024/06/06 02:24
Leetcode Permutation总结
含其中四题:Next Permutation, Permutations, Permutations II, Permutation Sequence

Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

class Solution {
public:
    void nextPermutation(vector &num) {
       
    }
};
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
分析:求下一个排列,例如:
1,2,3,4,5
1,2,3,5,4
1,2,4,3,5
...
1,2,5,4,3
1,3,2,4,5
...
大致分三个步骤:
(1)从右[len-1]往左[i],找到num[i] > num[i-1],如没有,即i==0,则num为从大到小排列的数组,则此时的下一个排列,为所有元素从小到大的排列;
(2)找到[num[i], num[len-1]]闭区间中比A[i-1]大的最小数num[minIndex],交换num[minIndex]和num[i-1],注:因为肯定有num[i] > num[i-1],所以minIndex从i开始;
(3)对新的[num[i], num[len-1]],从小到大排序。

class Solution {
public:
    void nextPermutation(vector &num) {
        int i = num.size() - 1;
        for(; i > 0; i--){
            if(num[i] > num[i - 1]) break;
        }
       
        if(i == 0){
            sort(num.begin(), num.end());
            return;
        }
       
        int tmp = num[i-1];
        int min = INT_MAX, minIndex = i;
        for(int j = i+1; j <= num.size() - 1; j++){
            if(num[j] > tmp && num[j] < min){
                minIndex = j;
                min = num[j];
            }
        }
        swap(num[i-1], num[minIndex]);
        sort(num.begin() + i, num.end());
    }
};

---------------------------------------------------------------------------------------------------------------------------------------------

Permutations

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].

class Solution {
public:
    vector > permute(vector &num) {
       
    }
};
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
方法一:利用上述写的next permutation 的程序,此时Permutation和Permutation II一样,不管数组中是否有元素重复
class Solution {
public:
    vector > permute(vector &num) {
        vector> result;
        sort(num.begin(), num.end());
        result.push_back(num);
        while(nextPermute(num)){
            result.push_back(num);
        }
       
        return result;
    }
    bool nextPermute(vector &num){
        int i = num.size() - 1;
        for(; i > 0; i--){
            if(num[i] > num[i-1]) break;
        }
        if(i == 0) return false;
       
       
        int min = INT_MAX;
        int minIndex = i;
        int tmp = num[i-1];
       
        for(int j = i+1; j <= num.size() - 1; j++){
            if(num[j] > tmp && num[j] < min){
                minIndex = j;
                min = num[j];
            }
        }
        swap(num[i-1], num[minIndex]);
        sort(num.begin() + i, num.end());
        return true;
    }   
};

方法二:暴力搜索法,递归
class Solution {
public:
    vector > permute(vector &num) {
        vector> result;
        vector path;
        dfs(result, path, num);
        return result;
    }
   
    void dfs(vector> &result, vector &path, vector &num){
        if(path.size() == num.size()){
            result.push_back(path);
            return;
        }
       
        for(auto nn : num){
            if(find(path.begin(), path.end(), nn) == path.end()){
                path.push_back(nn);
                dfs(result, path, num);
                path.pop_back();
            }
        }
       
    }
};


----------------------------------------------------------------------------------------------------------------------------------------------
Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2][1,2,1], and [2,1,1].

class Solution {
public:
    vector > permuteUnique(vector &num) {
       
    }
};
------------------------------------------------------------------------------------------------------------------------------------------------------------------
方法一:利用上述写的next permutation 的程序,此时Permutation和Permutation II一样,不管数组中是否有元素重复
class Solution {
public:
    vector > permuteUnique(vector &num) {
        vector> result;
        sort(num.begin(), num.end());
        result.push_back(num);
        while(nextPermute(num)){
            result.push_back(num);
        }
       
        return result;
    }
    bool nextPermute(vector &num){
        int i = num.size() - 1;
        for(; i > 0; i--){
            if(num[i] > num[i-1]) break;
        }
        if(i == 0) return false;
       
       
        int min = INT_MAX;
        int minIndex = i;
        int tmp = num[i-1];
       
        for(int j = i+1; j <= num.size() - 1; j++){
            if(num[j] > tmp && num[j] < min){
                minIndex = j;
                min = num[j];
            }
        }
        swap(num[i-1], num[minIndex]);
        sort(num.begin() + i, num.end());
        return true;
    } 
};

方法二:暴力搜索法,递归
统计词频,迭代~
class Solution {
public:
    vector > permuteUnique(vector &num) {
        vector> result;
        n = num.size();
        unordered_map count_map;
        for(int i = 0; i < num.size(); i++){
            if(count_map.find(num[i]) == count_map.end()){
                count_map[num[i]] = 1;
            }else{
                count_map[num[i]]++;
            }
        }
       
        vector path;
        dfs(result, path, count_map);
       
        return result;
    }
   
    size_t n;
   
    void dfs(vector> &result, vector &path, unordered_map count_map){
        if(path.size() == n){
            result.push_back(path);
            return;
        }
       
        for(auto it = count_map.begin(); it != count_map.end(); it++){
            int count = 0;
            for(int j = 0; j < path.size(); j++){
                if(path[j] == it->first) count++;
            }
           
            if(count < it->second){
                path.push_back(it->first);
                dfs(result, path, count_map);
                path.pop_back();
            }
           
        }  
    }
   
};
注:要从count_map的元素来迭代,因为其中无重复元素。。。num中有重复元素
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Permutation Sequence

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

 

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

class Solution {
public:
    string getPermutation(int n, int k) {
       
    }
};
--------------------------------------------------------------------------------------------------------------------------------------------------------
方法一,利用上述写的next permutation 的程序,此时Permutation和Permutation II一样,不管数组中是否有元素重复
class Solution {
public:
    string getPermutation(int n, int k) {
        int tolNum = 1;
        string sInit = "";
       
        for(int i = 1; i <= n; i++){
            tolNum *= i;
            char tmp = '0'+i;
            sInit.insert(sInit.end(), tmp);
        }
       
        k = k % tolNum;
        if(k == 0) k = tolNum;

        while(--k){
            sInit = nextPermutation(sInit);
               //cout<<sInit<<endl;
        }
        return sInit;
    }
   
    string nextPermutation(string &ss){
        int i = ss.size() - 1;
        for(; i > 0; i--){
            if(ss[i] > ss[i-1]) break;
        }
        if(i == 0 ) {
            sort(ss.begin(), ss.end());
            return ss;
        }
       
        int minIndex = i;
        for(int j = i+1; j < ss.size(); j++){
            if(ss[j] > ss[i-1] && ss[j] < ss[minIndex]){
                minIndex = j;
            }
        }
        swap(ss[minIndex], ss[i-1]);
        sort(ss.begin() + i, ss.end());
        return ss;
    }
};

方法二,康托编码:
原始字符串:123456789,从小到大排序
新的字符串:a1a2a3a4a5... ,假设长度为n,则(a2a3a4...),长度为n-1,有(n-1)!种排列
求第K个排列~~~"1234...n"为第1个排列
k = k-1;转换为从0开始,方便之后计算,原来是k从1开始
pos1 = k/(n-1)!          第k个排列的第1个字符为,原始字符串中pos1位置的字符
k = k%(n-1)!   更新k
pos2 = k/(n-2)!;         第k个排列的第2个字符为,原始字符串中pos2位置的字符
k = k%(n-2)!   更新k
依次循环,求出新的字符串,共n位,n次循环

class Solution {
public:
    string getPermutation(int n, int k) {
        string sInit = "";
        for(int i = 1; i <= n; i++){
            char tmp = '0' + i;
            sInit.insert(sInit.end(), tmp);
        }
       
        return getPermutation(sInit, k);
    }
   
    int f(int n){
        int result = 1;
        for(int i = 1; i <= n; i++){
            result = result * i;
        }
        return result;
    }
   
    string getPermutation(string &sInit, int k){
        string sResult = "";
        k--;
        int len = sInit.size();
        for(int i = 0; i <= len - 1; i++){
            int pos = k/f(len - 1 - i);
            sResult.insert(sResult.end(), sInit[pos]);
            sInit.erase(sInit.begin() + pos);
           
            k = k % f(len - 1 - i);
        }
        return sResult;
    }
   
};
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最偷懒的方法:利用STL里的next_permutation函数
vector num
bool next_permutation(num.begin(), num.end())
返回值是布尔类型,同时改变num中的值



http://blog.sina.com.cn/s/blog_ad29a69d0102uxcr.html
原创粉丝点击