算法设计与分析: 2-8 有重复元素的排列问题

2-8 有重复元素的排列问题


问题描述

R=r1,r2,,rn R = r 1 , r 2 , … , r n 是要进行排列的n个元素。其中元素 r1,r2,,rn r 1 , r 2 , … , r n 可能相同。试设计一个算法,列出R的所有不同排列。

编程任务
给定n 以及待排列的n 个元素。计算出这n 个元素的所有不同排列。


分治法

Java

import java.util.Scanner;

public class Main {

    private static char[] strToChar = new char[1000];
    private static int n;
    private static String inputStr;
    private static int total;

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        while(true){
            //restore total
            total = 0;

            System.out.println("Please input the length of string: ");
            n = input.nextInt();
            System.out.println("Please input a string: ");
            inputStr = input.next();
            System.out.println("------------------------------------------");
            strToChar = inputStr.toCharArray();

            permute(strToChar, 0, n-1);

            System.out.println("There are "+total+" different permutations!");
            System.out.println("------------------------------------------");
        }
    }

    private static void permute(char[] charList, int k, int m){
        if(k == m){
            total++;
            for(int i=0; i<=m; i++){
                System.out.print(charList[i]);
            }
            System.out.println();
            return;
        }

        for(int i=k; i<=m; i++){
            if(duplicate(charList, k, i)){
                swap(charList, k, i);
                permute(charList, k+1, m);
                swap(charList, k, i);
            }
        }
    }

    //第i个元素是否在前面元素[k...i-1]中出现过
    private static boolean duplicate(char[] charList, int k, int i){
        if(i > k){
            for(int j=k; jif(charList[j] == charList[i])
                    return false;
        }

        return true;
    }

    private static void swap(char[] charList, int k, int i){
        char temp;
        temp = charList[k];
        charList[k] = charList[i];
        charList[i] = temp;
    }
}

Input & Output

Please input the length of string: 
4
Please input a string: 
aacc
------------------------------------------
aacc
acac
acca
caac
caca
ccaa
There are 6 different permutations!
------------------------------------------
Please input the length of string: 
3
Please input a string: 
abc
------------------------------------------
abc
acb
bac
bca
cba
cab
There are 6 different permutations!
------------------------------------------
Please input the length of string: 
5
Please input a string: 
abbbb
------------------------------------------
abbbb
babbb
bbabb
bbbab
bbbba
There are 5 different permutations!
------------------------------------------
Please input the length of string: 

分治法 + Set

Java

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class Main {

    private static int n;
    private static String inputStr;
    private static char[] strToChar = new char[1000];

    private static String tmpPerm;

    private static Set permSet = new HashSet<>();

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        while(true){
            permSet.clear();

            System.out.println("Please input the length of string: ");
            n = input.nextInt();
            System.out.println("Please input a string: ");
            inputStr = input.next();
            System.out.println("------------------------------------------");
            strToChar = inputStr.toCharArray();

            permute(strToChar, 0, n-1);

            Iterator iterator = permSet.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }

            System.out.println("There are "+permSet.size()+" different permutations!");
            System.out.println("------------------------------------------");
        }
    }

    private static void permute(char[] charList, int k, int m){
        if(k == m){
            tmpPerm = String.valueOf(charList);
            permSet.add(tmpPerm);
            return;
        }

        for(int i=k; i<=m; i++){
            swap(charList, k, i);
            permute(charList, k+1, m);
            swap(charList, k, i);
        }
    }

    private static void swap(char[] charList, int k, int i){
        char temp;
        temp = charList[k];
        charList[k] = charList[i];
        charList[i] = temp;
    }
}

Input & Output

Please input the length of string: 
4
Please input a string: 
aacc
------------------------------------------
caca
acac
aacc
acca
caac
ccaa
There are 6 different permutations!
------------------------------------------
Please input the length of string: 
3
Please input a string: 
abc
------------------------------------------
acb
bca
abc
cba
bac
cab
There are 6 different permutations!
------------------------------------------
Please input the length of string: 
5
Please input a string: 
abbbb
------------------------------------------
bbbab
babbb
bbabb
bbbba
abbbb
There are 5 different permutations!
------------------------------------------
Please input the length of string:

深度优先搜索 DFS

Java

import java.util.Scanner;

public class Main {

    private static int[] counter = new int[1000];
    private static int[] charByDepth = new int[1000];

    private static int n;
    private static String inputStr;
    private static char[] strToChar = new char[1000];

    private static int total; //total permutations

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        while(true){
            //还原
            for(int i=0; i96]--;
            }
            total = 0;

            System.out.println("Please input the length of string: ");
            n = input.nextInt();
            System.out.println("Please input a string: ");
            inputStr = input.next();
            System.out.println("------------------------------------------");
            strToChar = inputStr.toCharArray();

            for(int i=0; i//记录每个字母在字符串中出现的次数
                counter[strToChar[i]-96]++;
            }

            dfs(1);

            System.out.println("There are "+total+" different permutations!");
            System.out.println("------------------------------------------");
        }
    }

    private static void dfs(int depth){
        int r;
        if(depth == n+1){
            total++;
            for(r=1; r<=n; r++){
                System.out.print(String.format("%c", charByDepth[r]+96));
            }
            System.out.println();
            return;
        }

        for(r=1; r<=26; r++){
            if(counter[r] > 0){//该字母没有取完
                charByDepth[depth] = r;//记录排列
                counter[r]--;
                dfs(depth+1);
                counter[r]++;//回溯
            }
        }
    }
}

Input & Output

Please input the length of string: 
4
Please input a string: 
aacc
------------------------------------------
aacc
acac
acca
caac
caca
ccaa
There are 6 different permutations!
------------------------------------------
Please input the length of string: 
3
Please input a string: 
abc
------------------------------------------
abc
acb
bac
bca
cab
cba
There are 6 different permutations!
------------------------------------------
Please input the length of string: 
5
Please input a string: 
abbbb
------------------------------------------
abbbb
babbb
bbabb
bbbab
bbbba
There are 5 different permutations!
------------------------------------------
Please input the length of string: 

Reference

王晓东《计算机算法设计与分析》(第3版)P44

你可能感兴趣的:(Algorithm,Java,分治递归,计算机算法设计与分析,计算机算法设计与分析)