我总结了全排列的各种题解,若有不全之处还请各位大大们慷慨指出.
1. 全排列之取球游戏
问题描述:
m球中取n个球,共有多少种取法
解题思路:
用递归思想解题.乍眼一看貌似递归无下手之处,其实每一个球只有两种情况:要么取, 要么不取. 若用m表示球的个数,n表示需要取的球的总数,那么当前球取则return fun(m - 1, n - 1) ; 不取则 return fun(m - 1, n);
代码实现:
github上相关代码:https://github.com/striner/javaCode/blob/master/Take%20the%20ball
import java.util.ArrayList; import java.util.List; import java.util.Scanner; //全排列练习 //1.取球游戏 m球中取n个球,共有多少种取法 public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int m = input.nextInt(); //共有m个球 int n = input.nextInt(); //取n个球 int num = fun(m, n); //共有num种取法 System.out.println(num); input.close(); } public static int fun(int m, int n) { if (n == 0) return 1; //m个球中取0个球,只有一种取法 if (m == n) return 1; //m个球中取m个球,只有一种取法 //假设有一个球做了标记,那么它就有两种取法: 取 或 不取 return fun(m - 1, n - 1) + fun(m - 1, n); } }
运行结果:
2. 全排列之字符串数组组合计数问题
问题描述:
求出输入字符串数组的全排列结果
解题思路:
用ArrayList<>集合存放每一种可能的排列.用fun(str.substring(0, i) + str.substring(i + 1))递归,将每一次的str.charAt(i)提取出来并拼到下一次递归的排列结果之前.
代码实现:
github上相关代码:https://github.com/striner/javaCode/blob/master/An%20array%20of%20strings%20of%20Full%20Permutation
//2. 字符串数组全排列 组合计数问题 //求出输入字符串数组的全排列结果 class Main1 { public static void main(String[] args) { Scanner input = new Scanner(System.in); String str = input.nextLine(); List<String> list = fun(str); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } input.close(); } public static List<String> fun(String str) { List<String> list = new ArrayList<>(); if (str.length() == 1) { list.add(str); return list; } for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); List<String> t = fun(str.substring(0, i) + str.substring(i + 1)); for (int j = 0; j < t.size(); j++) { list.add("" + c + t.get(j)); } } return list; } }
运行结果:
3.全排列之字符串数组组合计数问题(数组实现)
问题描述:
求出输入字符串数组的全排列结果
解题思路:
通过数组中每一个元素与其后面元素一一交换实现
代码实现:
//3. 用数组实现字符串数组的全排列 //通过数组中每一个元素与其后面元素一一交换实现 class Main2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); String str = input.nextLine(); char[] arr = str.toCharArray(); fun(arr, 0); input.close(); } public static void fun(char[] arr, int index) { //arr:待排数据 index: 考虑的当前位置(数组下标) if (index == arr.length - 1) { System.out.println(String.valueOf(arr)); return; } for (int i = index; i < arr.length; i++) { char ch = arr[i]; arr[i] = arr[index]; arr[index] = ch; //试探 fun(arr, index + 1); ch = arr[i]; arr[i] = arr[index]; arr[index] = ch; //回溯 } } }
运行结果:
4. 全排列之固定数目的组合问题
问题描述:
输入一串字符串数组,并中取3个数输出所有的可能结果
解题思路:
由于所需取出的球数仅为3种,可以直接暴力破解. 后文会介绍取出不定球数或球数很多时的解法.
代码实现:
github上相关代码:https://github.com/striner/javaCode/blob/master/The%20combinatorial%20problem%20of%20fixed%20number
//4. 固定数目的组合问题 组合枚举循环暴力法 //输入一串字符串数组,并中取3个数输出所有的可能结果 class Main3 { public static void main(String[] args) { Scanner input = new Scanner(System.in); String string = input.nextLine(); char[] ch = string.toCharArray(); fun(ch); input.close(); } public static void fun(char[] ch) { for (int i = 0; i < ch.length; i++) { for (int j = i + 1; j < ch.length; j++) { for (int k = j + 1; k < ch.length; k++) { System.out.println("" + ch[i] + ch[j] + ch[k]); } } } } }
运行结果:
5. 全排列之不定数目的组合问题
问题描述:
从输入的字符数组中取n个字母,都有哪些取法
解题思路:
采用组合枚举递归法解题,并用ArrayList对每种排列结果进行存储.
代码实现:
github上相关代码:https://github.com/striner/javaCode/blob/master/Variable%20number%20of%20combinatorial%20problems
//5. 不定数目的组合问题 组合枚举递归法 //从输入的字符数组中取n个字母,都有哪些取法 class Main4 { public static void main(String[] args) { Scanner input = new Scanner(System.in); String str = input.next(); int n = input.nextInt(); //串str中取n个字母 List<String> list = fun(str, n); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } input.close(); } public static List<String> fun(String str, int n) { List<String> list = new ArrayList<>(); if (n == 0) { list.add(""); return list; } for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); List<String> t = fun(str.substring(i + 1), n - 1); for (int j = 0; j < t.size(); j++) { list.add("" + ch + t.get(j)); } } return list; } }
运行结果:
6. 全排列之组合重复问题
问题描述:
"AABBBC" 取3个,都有哪些取法
解题思路:
此题用data[]数组对每个元素的最大个数进行存储,用x[]来表示每个元素所取的个数,采用递归方式求得每一种结果并打印输出.
代码实现:
github上相关代码:https://github.com/striner/javaCode/blob/master/Repeat%20combination
//6. 组合重复 //"AABBBC" 取3个,都有哪些取法 class Main5 { public static void main(String[] args) { int[] data = {2, 3, 1}; //每个元素的最大个数 限制条件 int[] x = new int[data.length]; //每个元素取几个 fun(data, x, 0, 3); } public static void fun(int[] data, int[] x, int k, int goal) { //k: 当前考虑的数的下标 goal:距离目标的剩余个数 if (k == x.length) { if (goal == 0) work(x); return; } for (int i = 0; i <= Math.min(data[k], goal); i++) { x[k] = i; fun(data, x, k + 1, goal - i); //试探 } x[k] = 0; //回溯 } public static void work(int[] x) { for (int i = 0; i < x.length; i++) { for (int j = 0; j < x[i]; j++) { //x[i]表示第i项的数最高出现几次 System.out.print((char)('A' + i)); } } System.out.println(); } }