【算法与数据结构】Java实现字符串的全排列及组合
注:本文记录了代码编写及调试过程,想直接浏览正确答案的请移步文章结尾。
一、字符串的全排列问题
1. 下面是最初的代码(答案有错误-重复输出)
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 while (sc.hasNext()) { 7 String str = sc.nextLine(); 8 char[] ch = str.toCharArray(); 9 //print(ch); 10 permutation(ch); 11 } 12 } 13 public static void permutation(char[] ch) { 14 if (ch == null || ch.length < 1) { 15 return; 16 }else { 17 permutation(ch, 0); 18 } 19 } 20 public static void permutation(char[] ch, int begin) { 21 char tmp ; 22 if (begin == ch.length - 1) { 23 print(ch); 24 System.out.println(); 25 return; 26 }else { 27 for (int i = 0; i < ch.length; i++) { 28 tmp = ch[begin]; 29 ch[begin] = ch[i]; 30 ch[i] = tmp; 31 permutation(ch, begin + 1); 32 tmp = ch[begin]; 33 ch[begin] = ch[i]; 34 ch[i] = tmp; 35 } 36 } 37 } 38 public static void print(char[] ch) { 39 for (int i = 0; i < ch.length; i++) { 40 System.out.print(ch[i]); 41 } 42 } 43 }
思想: 固定、交换、递归。
举例:输入abc,第一次先固定第一个字符a,使用递归交换a后面的字符(这里递归指的是a后面的字符串也是先固定第一个字符,之后再交换其后的字符)。
错误:输入abc,输出结果bac abc acb abc bac bca bca cba cab
2. debug过程
看到输出答案中有重复,猜想可能是字符交换的循环写的有问题,找到循环,第一眼就看到一个错误,for循环的迭代变量i初始值设置为0,这样达不到“固定”的效果,改之。输出正确。
结果
输入:abc
输出:abc acb bac bca cba cab
3.正确代码
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 while (sc.hasNext()) { 7 String str = sc.nextLine(); 8 char[] ch = str.toCharArray(); 9 permutation(ch); 10 } 11 } 12 public static void permutation(char[] ch) { 13 if (ch == null || ch.length < 1) { 14 return; 15 }else { 16 permutation(ch, 0); 17 } 18 } 19 public static void permutation(char[] ch, int begin) { 20 char tmp ; 21 if (begin == ch.length - 1) { 22 print(ch); 23 System.out.print(" "); 24 return; 25 }else { 26 for (int i = begin; i < ch.length; i++) { 27 tmp = ch[begin]; 28 ch[begin] = ch[i]; 29 ch[i] = tmp; 30 permutation(ch, begin + 1); 31 tmp = ch[begin]; 32 ch[begin] = ch[i]; 33 ch[i] = tmp; 34 } 35 } 36 } 37 public static void print(char[] ch) { 38 for (int i = 0; i < ch.length; i++) { 39 System.out.print(ch[i]); 40 } 41 } 42 }
二、字符串的组合问题
思想:分成两部分,(1)要打印的字符在第一部分,则在其后找其他(number-1)个字符。(2)要打印的字符不在第一部分,则在其后找其他(number)个字符
注:(1) 这里用了递归的方法。(2) number表示每次打印共有几个字符。
正确代码
注:程序中使用了stack容器保存结果,大家可以使用其他更加熟悉的容器。
1 import java.util.Scanner; 2 import java.util.Stack; 3 4 public class Main { 5 public static void main(String[] agrs) { 6 Scanner sc = new Scanner(System.in); 7 while (sc.hasNext()) { 8 String str = sc.nextLine(); 9 char[] ch = str.toCharArray(); 10 combine_str(ch); 11 } 12 } 13 public static void combine_str(char[] ch) { 14 if (ch == null || ch.length < 1) { 15 return; 16 } 17 Stack<Character> stack = new Stack<Character>(); 18 for (int i = 1; i <= ch.length; i++) { 19 combine_str(ch, 0, i, stack); 20 } 21 } 22 public static void combine_str(char[] ch, int begin, int number, Stack<Character> stack) { 23 if (number == 0) { 24 System.out.print(stack.toString() + " "); 25 return; 26 } 27 if (begin == ch.length ) { 28 return; 29 } 30 stack.push(ch[begin]); 31 combine_str(ch, begin + 1, number - 1, stack); 32 stack.pop(); 33 combine_str(ch, begin + 1, number, stack); 34 } 35 }
结果
输入: abc
输出: [a] [b] [c] [a, b] [a, c] [b, c] [a, b, c]