permutation 各种问题

1. 

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

bool next_permutation(vector<int>& num){
        int index_1 = num.size()-1;
        while (index_1 >0){
            if (num[index_1] <= num[index_1-1])
                index_1--;
            else
                break;
        }
        
        if (index_1==0)
            return false;
        
        int value = num[index_1-1];
        int index_2 = num.size();
        while (index_2 >0){
            if (num[index_2-1] <= value)
                index_2--;
            else
                break;
        }
        swap(num.at(index_1-1),num.at(index_2-1));
        reverse (num, index_1, num.size()-1);
        return true;
    }
    
    void reverse (vector<int>& num, int start, int end){
        int i = start;
        int j = end;
        while (i<j){
            swap(num.at(i),num.at(j));
            i++;
            j--;
        }
    }

2.  

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].

这题除了用next_permutaion, 还可以recursive列出数组的全排列

void permute(vector<int> num, int length, vector<vector<int> >& results,int index){
        if (index==length){
            if (find(results.begin(),results.end(),num) == results.end())
            results.push_back(num);
        }
                 
        for (int i = index; i < length; i++){
                if (num[i]!= num[index] || (i== index)){
                    swap(num[i],num[index]);
                    permute(num, num.size(), results,index+1);
                }
        }
    }

3. 

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<vector<int> > permuteUnique(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > results;
        if (num.size() == 0)
            return results;
            
        sort(num.begin(),num.end());  //STL 的sort
        results.push_back(num); //这个很重要,不然会少一个解
        while(next_permutation(num)){
            results.push_back(num);
        }
        return results;
    }
    
    bool next_permutation(vector<int>& num){
        int index_1 = num.size()-1;
        while (index_1 >0){
            if (num[index_1] <= num[index_1-1])
                index_1--;
            else
                break;
        }
        
        if (index_1==0)
            return false;
        
        int value = num[index_1-1];
        int index_2 = num.size();
        while (index_2 >0){
            if (num[index_2-1] <= value)
                index_2--;
            else
                break;
        }
        swap(num.at(index_1-1),num.at(index_2-1));
        reverse (num, index_1, num.size()-1);
        return true;
    }
    
    void reverse (vector<int>& num, int start, int end){
        int i = start;
        int j = end;
        while (i<j){
            swap(num.at(i),num.at(j));
            i++;
            j--;
        }
    }
};

4.  Kth permutation

class Solution {
public:
    void swap(int *A, int a, int b) {
     if(a>=b)
         return;
     int tmp=A[b];
     for(int i=b;i>=a+1;i--)
         A[i]=A[i-1];
     A[a]=tmp;
 }
 
 string getPermutation(int n, int k)
 {
        string result;
        int* A=new int[n];
        int cnt=1;
        for(int i=0;i<n;i++){
            A[i]=i+1;
            cnt*=i+1;
        }
        if(k>cnt)
            return result;
        cnt=cnt/n;
        for(int i=0;i<n;i++){
            int t=k/cnt;
            int r=k%cnt;
            if((r==0)&&(t>0))
                t--;
            swap(A,i,i+t);
            result.push_back(A[i]+'0');
            k=k-t*cnt;
            if(i<n-1)
               cnt=cnt/(n-i-1);
            else
                cnt=1;
        }
 }
    
};

1, 利用全排列  2, swap这个函数很重要!!


如果可以使用库函数

1. 可以使用sort 函数

MSDN中的定义:

template<class RanIt>
void sort(RanIt first, RanIt last); //--> 1)
template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr); //--> 2)


头文件:
#include <algorithm>
using namespace std;

1.默认的sort函数是按升序排。对应于1)
sort(a,a+n);   //两个参数分别为待排序数组的首地址和尾地址
2.可以自己写一个cmp函数,按特定意图进行排序。对应于2)
例如:
int cmp( const int &a, const int &b ){
    if( a > b )
       return 1;
    else
       return 0;
}
sort(a,a+n,cmp);
是对数组a降序排序
又如:
int cmp( const POINT &a, const POINT &b ){
    if( a.x < b.x )
       return 1;
    else
       if( a.x == b.x ){
          if( a.y < b.y )
             return 1;
          else
             return 0;
        }
       else
          return 0;
}
sort(a,a+n,cmp);
是先按x升序排序,若x值相等则按y升序排


2. STL中的next_permutation, 包含头文件#include <algorithm>

template<class BidirectionalIterator>
bool next_permutation(
      BidirectionalIterator _First, 
      BidirectionalIterator _Last
);
template<class BidirectionalIterator, class BinaryPredicate>
bool next_permutation(
      BidirectionalIterator _First, 
      BidirectionalIterator _Last,
      BinaryPredicate _Comp
 );
所以求 

void nextPermutation(vector<int> &num) {
       int n=num.size();
       if(n==0)
           return;
       int* A=new int[n];
       for(int i=0;i<n;i++)
           A[i]=num[i];
       next_permutation(A,A+n);
       for(int i=0;i<n;i++)
        num[i]=A[i];
}

错了,next_permutation只要是bidirectional的iterator都行,所以可以直接用

next_permutation(test.begin(),test.end());

要注意的是next_permutation的第二个参数以及返回值。

除了next_permutation, 还有pre_permutation



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值