字符串的排列和组合问题
Posted boris1221
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串的排列和组合问题相关的知识,希望对你有一定的参考价值。
1、字符串的全排列
题目:{a,b,c}要求输出{abc,acb,bac,bca,cab,cba}。
字符串全排列可以把字符串看成两个部分,第一个部分为它的一个字符,第二部分是后面的字符。
分两步完成:首先求所有可能出现在第一个位置的字符,即把第一个字符与后面的所有字符交换。第二步固定第一个字符,求后面所有字符的排列。从中可以看出是典型的递归思路。
1 public void helper(char[] array, int cur){ 2 if ( cur == array.length - 1 ) print(array); 3 else { 4 for ( int i = cur ; i < array.length ; i ++ ){ 5 swap(array,cur,i); 6 helper(array,cur+1); //固定第一个字符,对后面所有字符全排列 7 swap(array,i,cur); 8 } 9 } 10 }
如果给的字符中出现重复,即{a,b,c,c}这种情况,可以判断当前准备交换的字符,如果当前准备交换的字符已经在cur前面的字符中出现过了,就跳过,否则就交换。修改后方法如下:
1 public void helper(char[] array, int cur){ 2 if ( cur == array.length - 1 ) print(array); 3 else { 4 for ( int i = cur ; i < array.length ; i ++ ) { 5 if (!isExit(array, cur, i)) { 6 swap(array, cur, i); 7 helper(array, cur + 1); //固定第一个字符,对后面所有字符全排列 8 swap(array, i, cur); 9 } 10 } 11 } 12 } 13 private boolean isExit(char[] array, int cur, int i) { 14 for ( int k = cur ; k < i ; k ++ ){ 15 if ( array[k] == array[i] ) return true; 16 } 17 return false 18 }
2、字符串组合
题目:{a,b,c}要求输出{a,b,c,ab,ac,bc,abc}。
分析,可以将题目分成小问题来理解,1个字符的组合+2个字符的组合+3个字符的组合,因此我们只要找到一般的方法,即从n个字符中找m个字符的组合就可以了。
我们可以把n个字符分成两部分,第一个字符和其他所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符,从中可以看出又是个递归的过程。
1 Stack<Character> stack = new Stack<>(); 2 public void helper(char[] array){ 3 for ( int i = 1 ; i <= array.length ; i ++ ) 4 combination(array,0,i); 5 } 6 private void combination(char[] strArr, int begin, int num) { 7 if (num == 0) { 8 System.out.println(stack); 9 return; 10 } 11 if (begin >= strArr.length) { 12 return; 13 } else { 14 //把第一个字符放入组合中,在剩余的字符中选取num-1个字符 15 stack.push(strArr[begin]); 16 combination(strArr, begin + 1, num - 1); 17 //组合里不包含第一个字符,则下一步在剩余的字符中选取num个字符 18 stack.pop(); 19 combination(strArr, begin + 1, num); 20 } 21 }
helper函数表示求长度为i的全排列。
还有一种更nb的方法,因为组合问题,比如3个元素的组合就有2^3-1种,所以不妨给他们进行编号,就像上面的问题,从a——abc一次编号为 001——111。1就代表该位置出现字符。例如:001->c,010->b,101->ac......,所以原题就是要求输出"001"-"111"这2^n-1个组合对应的字符串。
1 public static void main(String[] args) { 2 3 String s = "abc"; 4 ArrayList<String> result = combineString(s); 5 for(String r : result){ 6 System.out.println(r); 7 } 8 } 9 10 private static ArrayList<String> combineString(String s) { 11 int len = s.length(); 12 ArrayList<String> list = new ArrayList<String>(); 13 int count = (int) (Math.pow(2, len)); 14 for(int i = 1; i < count; ++i){ 15 String temp = ""; 16 String str = Integer.toBinaryString(i); 17 while(str.length() < len){ 18 str = "0" + str; 19 } 20 for(int j = 0; j < str.length(); ++j){ 21 if(str.charAt(j) == ‘1‘){ 22 temp += s.charAt(j); 23 } 24 } 25 list.add(temp); 26 } 27 return list; 28 }
以上是关于字符串的排列和组合问题的主要内容,如果未能解决你的问题,请参考以下文章