字符串的排列与组合及八皇后等其他相关问题

来源:互联网 发布:淘宝商城玩具店 编辑:程序博客网 时间:2024/05/21 12:39

 

1.     字符串全排列(不去重)

【题目】输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。

参考:http://www.cnblogs.com/GoAhead/archive/2012/05/30/2526563.html

【分析】采用递归方法:


最外层的循环过程(下面指的是位置交换):

0与0交换abc——内部循环是:1与1交换,输出abc;1与2交换输出acb

0与1交换bac——内部循环是:1与1交换,输出bac;1与2交换输出bca

0与2交换cba——内部循环是:1与1交换,输出cba;1与2交换输出cab

 

/**  * 创建时间:2014年9月7日下午3:29:42  * 项目名称:Test  * @author Cao Yanfeng  北京大学 * @since JDK 1.6.0_21  * 类说明:  字符全排列,没有去重 */public classPermutationTest {     /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        char[] array={'a','b','c'};        printPermutation(array, 0, array.length);     }    public static void printPermutation(char[] array,int start,int end) {        if (start==end-1) {            System.out.println(new String(array));        }else {            for (int k = start; k < end; k++) {                swap(array, k, start);                printPermutation(array, start+1, end);                swap(array, k, start);            }        }    }    public static void swap(char[] array,int i,int j) {        if (array[i]!=array[j]) {            array[i]^=array[j];            array[j]^=array[i];            array[i]^=array[j];        }    }}


2.     字符串全排列(去重)

【参考】http://blog.csdn.net/hackbuteer1/article/details/7462447

【分析】假设是aac

最外层的循环过程(下面指的是位置交换):

0与0交换aac——内部循环是:1与1交换,输出aac;1与2交换输出aca

01交换aac——内部循环是:11交换,输出aac12交换输出aca

0与2交换caa——内部循环是:1与1交换,输出caa;12交换输出caa

所以要阻断上面红色部分,只要交换条件是:待交换的两个数下标相同(比如上面的原地交换,两个数相等)或者待交换的两个数不相等,也就是说上面的0与0仍能交换,0与1、1与2就不能交换了。

下面程序跟上面相比仅仅加了一行语句:if (k==start||array[k]!=array[start])

/

**  * 创建时间:2014年9月7日下午3:29:42  * 项目名称:Test  * @author Cao Yanfeng  北京大学 * @since JDK 1.6.0_21  * 类说明:  字符全排列,去重 */public classPermutationTest {     /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        char[] array={'a','a','c'};        printPermutation(array, 0, array.length);     }    public static void printPermutation(char[] array,int start,int end) {        if (start==end-1) {            System.out.println(new String(array));        }else {            for (int k = start; k < end; k++) {                if (k==start||array[k]!=array[start]) {                    swap(array, k, start);                    printPermutation(array, start+1, end);                    swap(array, k, start);                }else {                    continue;                }                                          }        }    }    public static void swap(char[] array,int i,int j) {        if (array[i]!=array[j]) {            array[i]^=array[j];            array[j]^=array[i];            array[i]^=array[j];        }    } }

3.     字符串的所有组合/字符串的所有子集(不去重)

参考:http://blog.csdn.net/xuyuxin8145/article/details/6637692

【分析】a-b-c的组合可以用递归来实现。假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。

/**  * 创建时间:2014年9月7日下午4:42:33  * 项目名称:Test  * @author Cao Yanfeng  北京大学 * @since JDK 1.6.0_21  * 类说明:  字符串的所有组合,不去重 */public classCombination {     /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        char[] array={'a','b','c'};          combination(array);     }    public static void combination(char[] array) {        if (array==null||array.length==0) {            return;        }        ArrayList<Character>result=newArrayList<Character>();        for (int i = 1; i <=array.length; i++) {            combination_m(array, 0, i, result);               }    }    public static void combination_m (char[] array,int begin,int m,ArrayList<Character>result){        if (m==0) {            System.out.println(result.toString());            return;        }        if (begin==array.length) {            return;        }        /*选择这个元素*/        result.add(array[begin]);        combination_m(array, begin+1, m-1, result);        /*不选择这个元素*/        result.remove((Character)array[begin]);        combination_m(array, begin+1, m, result);    } }


4.     八皇后问题

【问题】在8×8的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。


【分析】columnIndex ={0,1,2,3,4,5,6,7}表示的分别是0~7列的行号,所以不会有位于一行的皇后,也不会有位于一列的皇后。八皇后问题,即获得{0,1,2,3,4,5,6,7}所有排列,排除斜对角线情况即可。斜对角的条件是:(i - j == columnIndex[i] - columnIndex[j]) ||( j - i ==columnIndex[i] - columnIndex[j]),例如{0,1,*,*,*,*,*,*}肯定不行,0与1位于对角线。注意,这里为了在递归过程中统计次数,需要传址调用,所以定义了一个Counter类,不能使用int或Integer。

/** * 创建时间:2014年9月7日下午9:03:03 项目名称:Test * * @author Cao Yanfeng Peking University * @since JDK 1.6.0_21 类说明:八皇后问题,即获得{0,1,2,3,4,5,6,7}所有排列,排除斜对角线情况即可 * 注意:{0,1,2,3,4,5,6,7}表示的分别是0~7列的行号,所以不会有位于一行的皇后,也不会有位于一列的皇后。 */public classEightQueenTest {     /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        eightQueue();     }     public static void eightQueue() {        final int queens = 8;        int[] columnIndex = new int[queens];        /* 初始化 */        for (int i = 0; i < columnIndex.length; i++) {            columnIndex[i] = i;        }        Countercounter=new Counter();        counter.setCounter(0);        /*递归的全排列*/        permutation(columnIndex, 0, columnIndex.length,counter);    }     public static void permutation(int[] columnIndex, int start, int end,Counter counter) {        /*只要当前的指针stat指向了最后一个元素,则递归探底*/        if (start == end - 1) {            if (check(columnIndex)) {                counter.setCounter(counter.getCounter()+1);                System.out.print("第"+counter.getCounter()+"种排列:");                for (int i = 0; i < columnIndex.length; i++) {                    System.out.print(columnIndex[i]);                }                System.out.println();            }         }else{            for (int k = start; k < end; k++) {                swap(columnIndex, k, start);                permutation(columnIndex, start + 1, end,counter);                swap(columnIndex, k, start);            }        }    }   /*查看该数组是否有两个或以上的元素在斜对角线上*/    public static boolean check(int[] columnIndex) {        for (int i = 0; i < columnIndex.length; i++) {            for (int j = i + 1; j < columnIndex.length; j++) {                if (i - j == columnIndex[i] - columnIndex[j]                        ||j - i == columnIndex[i] - columnIndex[j])                    return false;            }        }        return true;    }     public static void swap(int[] array, int i, int j) {        if (array[i] != array[j]) {            array[i] ^= array[j];            array[j] ^= array[i];            array[i] ^= array[j];        }    } }class Counter{    int counter;     public int getCounter() {        return counter;    }     public void setCounter(int counter) {        this.counter = counter;    }   }


5.     数组array中所有元素都只出现一次,给的一个sum,求array的子集和等于sum的所有子集。

参考:http://blog.csdn.net/hackbuteer1/article/details/7462447

【分析】获得array的所有组合,然后判断即可。对上面的主题3“字符串的所有组合/字符串的所有子集合”进行一些修改即可。

/** * 创建时间:2014年9月7日下午9:43:24 项目名称:Test * * @author Cao Yanfeng Peking University * @since JDK 1.6.0_21 类说明:数组的所有子集合中,子集合和等于给定数的集合本质是组合问题 */public classCombinationTest2 {    /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        int[] array = { 1, 2, 3, 4, 2 };        combination(array, 5);    }     public static void combination(int[] array, int sum) {        if (array == null || array.length == 0) {            return;        }        ArrayList<Integer>result= newArrayList<Integer>();        for (int i = 1; i <= array.length; i++) {            combination_m(array, 0, i, result, sum);         }    }     public static void combination_m(int[] array, int begin, int m,            ArrayList<Integer>result,intsum){        if (m == 0) {            for (Integer integer : result) {                sum -= integer;            }            if (sum == 0) {                System.out.println(result.toString());            }            return;        }        if (begin == array.length) {            return;        }        /* 选择这个元素 */        result.add(array[begin]);        combination_m(array, begin + 1, m - 1, result, sum);        /* 不选择这个元素 */        result.remove((Integer) array[begin]);        combination_m(array, begin + 1, m, result, sum);    }}


*******************************************************************************

这里遗留了一个问题就是组合有重复的情况,如何去重复。待研究。。。。

 

0 0
原创粉丝点击