带重复数字的全排列

一道又重复数字的全排列的问题,用set保存,然后直接回溯。这这种做法,效率比较低,没有去剪枝,从而像1,1,1,1,1这样的序列都需要回溯很多次。今天写了一个剪枝的。
Java代码
  1.   
  2. public class Permutation   
  3. {   
  4.     private int[] a;   
  5.        
  6.     public Permutation(int[] a)   
  7.     {   
  8.         this.a = a;   
  9.     }   
  10.     public  boolean isOk(int b,int e){//判断是否重复   
  11.         if(b < e){   
  12.             for(int i = b; i < e; i++){   
  13.                 if(a[i] == a[e])   
  14.                     return false;   
  15.             }   
  16.         }   
  17.         return true;   
  18.     }   
  19.        
  20.     public void permutation(int k){   
  21.         if(k >= a.length){   
  22.             print();   
  23.         }else{   
  24.             for(int i = k; i < a.length; i++){   
  25.                 if(isOk(k,i)){   
  26.                     swap(i,k);   
  27.                     permutation( k+1 );   
  28.                     swap(i,k);   
  29.                 }   
  30.             }   
  31.         }   
  32.            
  33.     }   
  34.        
  35.     private void swap( int i, int k )   
  36.     {   
  37.         int temp = a[i];   
  38.         a[i] = a[k];   
  39.         a[k] = temp;   
  40.     }   
  41.        
  42.     private void print()   
  43.     {   
  44.         forint i = 0; i < a.length; i++ )   
  45.         {   
  46.             System.out.print(a[i] + " ");   
  47.         }   
  48.         System.out.println();   
  49.     }   
  50.        
  51.     public static void main( String[] args )   
  52.     {   
  53.         Permutation p = new Permutation(new int[]{1,2,2,2});   
  54.         p.permutation( 0 );   
  55.     }   
  56. }  
public class Permutation
{
    private int[] a;
    
    public Permutation(int[] a)
    {
        this.a = a;
    }
    public  boolean isOk(int b,int e){//判断是否重复
        if(b < e){
            for(int i = b; i < e; i++){
                if(a[i] == a[e])
                    return false;
            }
        }
        return true;
    }
    
    public void permutation(int k){
        if(k >= a.length){
            print();
        }else{
            for(int i = k; i < a.length; i++){
                if(isOk(k,i)){
                    swap(i,k);
                    permutation( k+1 );
                    swap(i,k);
                }
            }
        }
        
    }
    
    private void swap( int i, int k )
    {
        int temp = a[i];
        a[i] = a[k];
        a[k] = temp;
    }
    
    private void print()
    {
        for( int i = 0; i < a.length; i++ )
        {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }
    
    public static void main( String[] args )
    {
        Permutation p = new Permutation(new int[]{1,2,2,2});
        p.permutation( 0 );
    }
}


c++ STL algorithm中有next_permutation可以直接调用,ACM的时候经常偷懒用这个,呵呵。
学以致用:poj 1731
http://acm.pku.edu.cn/JudgeOnline/problem?id=1731
Cpp代码 复制代码
  1. #include<iostream>   
  2. #include<algorithm>   
  3. #include<vector>   
  4. #include<string>   
  5. using namespace std;   
  6.   
  7. string goods;   
  8. vector<string> v;   
  9.   
  10. void swap(string &str,int i, int j){   
  11.     char temp = str[i];   
  12.     str[i] = str[j];   
  13.     str[j] = temp;   
  14. }   
  15.   
  16. bool ok(int i, int j){   
  17.     if( i < j){   
  18.         for(int k = i; k < j; k++){   
  19.             if(goods[k] == goods[j])   
  20.                 return false;   
  21.         }   
  22.     }   
  23.     return true;   
  24. }   
  25. void backtrack(int i){   
  26.     if(i >= goods.length()){   
  27.          v.push_back(goods);   
  28.     }   
  29.        
  30.     for(int j = i; j < goods.length(); j++){   
  31.         if(ok(i,j)){   
  32.             swap(goods,i,j);   
  33.             backtrack(i + 1);   
  34.             swap(goods,i,j);   
  35.         }   
  36.     }   
  37. }   
  38.   
  39. int main(){   
  40.     cin >> goods;   
  41.     backtrack(0);   
  42.     sort(v.begin(),v.end());   
  43.     for(int i = 0; i < v.size(); i++){   
  44.         cout << v[i] << endl;   
  45.     }   
  46. }  
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;

string goods;
vector<string> v;

void swap(string &str,int i, int j){
	char temp = str[i];
	str[i] = str[j];
	str[j] = temp;
}

bool ok(int i, int j){
	if( i < j){
		for(int k = i; k < j; k++){
			if(goods[k] == goods[j])
				return false;
		}
	}
	return true;
}
void backtrack(int i){
	if(i >= goods.length()){
		 v.push_back(goods);
	}
	
	for(int j = i; j < goods.length(); j++){
		if(ok(i,j)){
			swap(goods,i,j);
			backtrack(i + 1);
			swap(goods,i,j);
		}
	}
}

int main(){
	cin >> goods;
	backtrack(0);
	sort(v.begin(),v.end());
	for(int i = 0; i < v.size(); i++){
		cout << v[i] << endl;
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值