Permutations II

本文探讨了在可能包含重复元素的数集中生成唯一排列的方法,通过两种算法优化了效率,详细介绍了排序与循环移位的基本思想,并通过实例演示了算法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Permutations II Mar 17 '12

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


思路一:用set来装vector,可以直接用Permutations的代码,但并没有从根本上解决产生重复排列的问题,效率也不高

class Solution {
public:

 int factorial(int n)  
    {  
        return (n==1)?1:n*factorial(n-1);  
    }  
      
    void nextPermutation(vector<int> &num) {    
        int i = 0;    
        int k = num.size();    
            
        while(k-->=1)    
        {    
            if(num[k] > num[k-1])    
            {    
                i = k;    
                break;    
            }    
        }    
        int j= i-1;    
        k = num.size();    
        while(k-- != i-1)    
        {    
            if(num[k] > num[i-1]) {    
                j = k;    
                break;    
            }    
        }              
        swap(num[i-1],num[j]);        
            
        reverse(num.begin()+i,num.end());    
    }    
      
  
    vector<vector<int> > permuteUnique(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int>> ret;  
        set<vector<int>> set;
          
        int N = factorial(num.size());  
        for(int i = 0;i < N;i++){  
            set.insert(num);  
            nextPermutation(num);  
        }  
        ret.insert(ret.end(),set.begin(),set.end());
        return ret; 
    }
};

800 milli secs


思路二:还是在permute的基础上,重点见注释

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>> ret;  
          
        sort(num.begin(),num.end());  //重点在这步排序
        while(1){
            ret.push_back(num);  
            int i = 0;    
            int k = num.size();    
                
            while(k-->=1)    
            {    
                if(num[k] > num[k-1])    //这里是>号,所以在排好序的情况下是否有重复并无影响
                {    
                    i = k;    
                    break;    
                }    
            }    
            if(k==-1) break;          //判断是否生成了所有排列
            int j= i-1;    
            k = num.size();    
            while(k-- != i-1)    
            {    
                if(num[k] > num[i-1]) {    
                    j = k;    
                    break;    
                }    
            }              
            swap(num[i-1],num[j]);        
                
            reverse(num.begin()+i,num.end());    
        }  
        return ret;  
    }  
}; 

160 milli secs


其它方法暂不实现,有空再讨论吧

可以看一下这篇http://www.cnblogs.com/remlostime/archive/2012/11/13/2768816.html,提到DFS的方法


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值