`

带重复数字的全排列

J# 
阅读更多
上次gx同学问我一道又重复数字的全排列的问题,我当时用set保存,然后直接回溯。这这种做法,效率比较低,没有去剪枝,从而像1,1,1,1,1这样的序列都需要回溯很多次。今天写了一个剪枝的。

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
#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;
	}
}

poj1256 http://acm.pku.edu.cn/JudgeOnline/problem?id=1256
这道题需要一种特殊的数序输出:
An upper case letter goes before the corresponding lower case letter.
So the right order of letters is 'A'<'a'<'B'<'b'<...<'Z'<'z'.
我们只需要定义一个正确的比较函数就可以了
bool cmp(const string &str1,const string &str2){  
    int i;  
    int m_len = min(str1.length(), str2.length());  
    for(i = 0; i < m_len; i++){  
        if(str1[i] != str2[i])  
            break;  
    }  
  
    if(i == m_len){  
        return str1.length() < str2.length();  
    }else if(tolower(str1[i]) == tolower(str2[i])) {  
        return str1[i] < str2[i];  
    }else{  
        return tolower(str1[i]) < tolower(str2[i]);  
    }  
}  

或者
bool cmp(char c1,char c2){
	if(tolower(c1) == tolower(c2)) 
		return c1 < c2;
	else
		return tolower(c1) < tolower(c2);
}

这样我们的代码就出来了:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;

string str;
vector<string> permutations;

bool cmp(const string &str1,const string &str2){
	int i;
	int m_len = min(str1.length(), str2.length());
	for(i = 0; i < m_len; i++){
		if(str1[i] != str2[i])
			break;
	}

	if(i == m_len){
		return str1.length() < str2.length();
	}else if(tolower(str1[i]) == tolower(str2[i])) {
		return str1[i] < str2[i];
	}else{
		return tolower(str1[i]) < tolower(str2[i]);
	}
}

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

bool isOk(int i,int j){
	if(i < j){
		int k;
		for(k = i; k < j; k++){
			if(str[k] == str[j])
				return false;
		}
	}
	return true;
}

void backtrack(int i){
	if( i >= str.length()){
		permutations.push_back(str);
		return;
	}

	int j;
	for(j = i; j < str.length(); j++){
		if(isOk(i,j)){
			swap(i,j);
			backtrack(i+1);
			swap(i,j);
		}
	}
}

int main(){
	int n;
	cin >> n;
	int i,j;
	for(i = 0; i < n; i++){
		cin >> str;
		permutations.clear();
		backtrack(0);
		sort(permutations.begin(),permutations.end(),cmp);
		for(j = 0; j < permutations.size(); j++){
			cout << permutations[j] << endl;
		}
	}
}

我们还是用STL来爽爽这道题吧:
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;

string str;

bool cmp(char c1,char c2){
	if(tolower(c1) == tolower(c2)) 
		return c1 < c2;
	else
		return tolower(c1) < tolower(c2);
}

int main(){
	int n;
	cin >> n;
	int i,j;
	for(i = 0; i < n; i++){
		cin >> str;
		sort(str.begin(),str.end(),cmp);
		cout << str << endl;
		while(next_permutation(str.begin(),str.end(),cmp)){
			cout << str << endl;
		}
	}
	return 0;
}
1
0
分享到:
评论

相关推荐

    C语言重复数全排列的代码

    生成这些字符的不重复的全排列,并将结果打印到标准输出上。 【输入形式】 从标准输入上读入一个由字母、数字组成的字符串,字符串的长度小于100,其中包含重复的字符。 【输出形式】 向标准输出印...

    有重复数字的全排列代码

    算法分析课程作业,C语言编写,可能需要用input.txt输入,有重复数字的全排列代码

    输出n个数字的全排列(可重复)

    1、输入n个数(不重复),求n个数字的全排列 如:n=3 全排列的数字为 1 2 3 则输出 123 132 213 231 321 312 2、输入n和k(n》=k)求n个数字的(n,k)排列 如n=3,k=2 输入的三个数位1 2 3 则输出 12 13 21 23 31...

    回溯法 - 输出自然数1到n所有不重复的排列,即n的全排列

    输出自然数1到n的所有不重复的排列,即n的全排列。

    使用swap函数求解带有重复字符串的全排列

    这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数。下面给出...

    全排列acc pascal程序加题解 全排列

    由1~n组成的所有不重复的数字序列,每行一个序列。 Sample Input 3 Sample Output 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 Source elba 程序如下 const maxn=1000; var a:array[0..maxn] of longint; n,k:long...

    去重全排列的递归实现

    去重全排列的递归实现 去掉重复数字的 全排列的 递归实现

    使用swap求解不重复字符串的全排列

    为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。...因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了:

    python 实现全排列 II

    # 给定一个可包含重复数字的序列,返回所有不重复的全排列 # 示例: # 输入: [1,1,2] # 输出: # [ # [1,1,2], # [1,2,1], # [2,1,1] # ]

    全排列数生成

    各行上的全排列不重复。输出各行遵循“小数优先”原则, 在各全排列中,较小的数尽量靠前输出。如果将每行上的输出看成一个数字,则所有输出构成升序数列。具体格式见输出样例。 【样例输入1】1 【样例输出1】1 ...

    Rogerspy#LeetCode-Py-1#剑指 Offer II 083. 没有重复元素集合的全排列1

    剑指 Offer II 083. 没有重复元素集合的全排列标签:数组、回溯难度:中等题目大意给定一个不含重复数字的数组 nums 。若未被访问过则将其加入排列中

    tesla-peer#LeetCode-Python-#剑指 Offer II 083. 没有重复元素集合的全排列1

    剑指 Offer II 083. 没有重复元素集合的全排列标签:数组、回溯难度:中等题目大意给定一个不含重复数字的数组 nums 。若未被访问过则将其加入排列中

    finesure2017#LeetCode-Py-1#剑指 Offer II 084. 含有重复元素集合的全排列 1

    剑指 Offer II 084. 含有重复元素集合的全排列标签:数组、回溯难度:中等题目大意给定一个可包含重复数字的序列 nums 。解题思路这道题跟「剑指 O

    排列程序 给出一个序列(无重复元素),输出其全部排列

    求一个序列的全排列,字典序,序列中的元素无重复,在实际应用过程中,可以按下标来做计算

    shuxinyin#leetcode#[47]全排列 II1

    给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。示例 1:输出:示例 2:输出:[[1,2,3],[1,3,2],[2,1,3],

    c 语言 1 2 3 4 全排列 三位数不重复

    题目:有 1、2、3、4 四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位、十位、个位的数字都是 1、2、3、4,组成所有的排列后再去掉不满足条件的排列。

    LeetCode 46. 全排列

    给定一个 没有重复 数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 解题思路 思路:深度优化搜索 先看题目,以所给数组 [1, 2...

    C++全排列中递归交换法实例详解

    输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。 输入格式 一个整数n。 输出格式 由1~n组成的所有不重复的数字序列,每行一个序列。 每个数字保留 5个场宽。 ...

    Python算法题源代码-LeetCode(力扣)-全排列

    给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例 2: 输入:nums = ...

    JingLuoChen#web-summary#全排列1

    全排列给定一个 没有重复 数字的序列,返回其所有可能的全排列。示例:输入: [1,2,3]输出:var permute = function(nums) {

Global site tag (gtag.js) - Google Analytics