Java解决排列组合问题——深度优先遍历
2018-03-15 23:05
423 查看
[b]问题1:
[/b]假设袋子里有编号为1,2,...,m这m个球。现在每次从袋子中取一个球几下编号,放回袋中再取,取n次作为一组,枚举所有可能的情况。
分析:每一次取都有m种可能的情况,因此一共有
种情况。
这里我们取m = 3, n = 4,则有
种不同的情况。
代码:
输出:
问题2:
假设袋子里有编号为1,2,...,m这m个球。先后从袋子中取出n个球,依次记录编号,枚举所有可能的情况。
分析:这是排列问题,应该有
种情况。
这里取m = 5, n = 3,
。
和问题1相比,唯一的区别是排列中不可以有重复。因此开了used数组用以标记是否已经访问。
代码:
输出:
问题3: 从m个球里(编号为1,2,3...,m)一次取n个球,其中m>n,记录取出球的编号,枚举所有的可能性。
分析:这是组合问题。因该有
种可能性。
这里,我们取m = 8, n = 4. 因此有
种可能。
代码:
输出:
[/b]假设袋子里有编号为1,2,...,m这m个球。现在每次从袋子中取一个球几下编号,放回袋中再取,取n次作为一组,枚举所有可能的情况。
分析:每一次取都有m种可能的情况,因此一共有
种情况。
这里我们取m = 3, n = 4,则有
种不同的情况。
代码:
import java.util.Stack; public class Test { static int cnt = 0; static Stack<Integer> s = new Stack<Integer>(); /** * 递归方法,当实际选取的小球数目与要求选取的小球数目相同时,跳出递归 * @param minv - 小球编号的最小值 * @param maxv - 小球编号的最大值 * @param curnum - 当前已经确定的小球的个数 * @param maxnum - 要选取的小球的数目 */ public static void kase1(int minv,int maxv,int curnum, int maxnum){ if(curnum == maxnum){ cnt++; System.out.println(s); return; } for(int i = minv; i <= maxv; i++){ s.push(i); kase1(minv, maxv, curnum+1, maxnum); s.pop(); } } public static void main(String[] args){ kase1(1, 3, 0, 4); System.out.println(cnt); } }
输出:
[1, 1, 1, 1] [1, 1, 1, 2] [1, 1, 1, 3] [1, 1, 2, 1] [1, 1, 2, 2] [1, 1, 2, 3] [1, 1, 3, 1] [1, 1, 3, 2] [1, 1, 3, 3] [1, 2, 1, 1] [1, 2, 1, 2] [1, 2, 1, 3] [1, 2, 2, 1] [1, 2, 2, 2] [1, 2, 2, 3] [1, 2, 3, 1] [1, 2, 3, 2] [1, 2, 3, 3] [1, 3, 1, 1] [1, 3, 1, 2] [1, 3, 1, 3] [1, 3, 2, 1] [1, 3, 2, 2] [1, 3, 2, 3] [1, 3, 3, 1] [1, 3, 3, 2] [1, 3, 3, 3] [2, 1, 1, 1] [2, 1, 1, 2] [2, 1, 1, 3] [2, 1, 2, 1] [2, 1, 2, 2] [2, 1, 2, 3] [2, 1, 3, 1] [2, 1, 3, 2] [2, 1, 3, 3] [2, 2, 1, 1] [2, 2, 1, 2] [2, 2, 1, 3] [2, 2, 2, 1] [2, 2, 2, 2] [2, 2, 2, 3] [2, 2, 3, 1] [2, 2, 3, 2] [2, 2, 3, 3] [2, 3, 1, 1] [2, 3, 1, 2] [2, 3, 1, 3] [2, 3, 2, 1] [2, 3, 2, 2] [2, 3, 2, 3] [2, 3, 3, 1] [2, 3, 3, 2] [2, 3, 3, 3] [3, 1, 1, 1] [3, 1, 1, 2] [3, 1, 1, 3] [3, 1, 2, 1] [3, 1, 2, 2] [3, 1, 2, 3] [3, 1, 3, 1] [3, 1, 3, 2] [3, 1, 3, 3] [3, 2, 1, 1] [3, 2, 1, 2] [3, 2, 1, 3] [3, 2, 2, 1] [3, 2, 2, 2] [3, 2, 2, 3] [3, 2, 3, 1] [3, 2, 3, 2] [3, 2, 3, 3] [3, 3, 1, 1] [3, 3, 1, 2] [3, 3, 1, 3] [3, 3, 2, 1] [3, 3, 2, 2] [3, 3, 2, 3] [3, 3, 3, 1] [3, 3, 3, 2] [3, 3, 3, 3] 81
问题2:
假设袋子里有编号为1,2,...,m这m个球。先后从袋子中取出n个球,依次记录编号,枚举所有可能的情况。
分析:这是排列问题,应该有
种情况。
这里取m = 5, n = 3,
。
和问题1相比,唯一的区别是排列中不可以有重复。因此开了used数组用以标记是否已经访问。
代码:
import java.util.Stack; public class Test { static int cnt = 0; static Stack<Integer> s = new Stack<Integer>(); static boolean[] used = new boolean[10000]; /** * 递归方法,当实际选取的小球数目与要求选取的小球数目相同时,跳出递归 * @param minv - 小球编号的最小值 * @param maxv - 小球编号的最大值 * @param curnum - 当前已经确定的小球的个数 * @param maxnum - 要选取的小球的数目 */ public static void kase2(int minv,int maxv,int curnum, int maxnum){ if(curnum == maxnum){ cnt++; System.out.println(s); return; } for(int i = minv; i <= maxv; i++){ if(!used[i]){ s.push(i); used[i] = true; kase2(minv, maxv, curnum+1, maxnum); s.pop(); used[i] = false; } } } public static void main(String[] args){ kase2(1, 5, 0, 3); System.out.println(cnt); } }
输出:
[1, 2, 3] [1, 2, 4] [1, 2, 5] [1, 3, 2] [1, 3, 4] [1, 3, 5] [1, 4, 2] [1, 4, 3] [1, 4, 5] [1, 5, 2] [1, 5, 3] [1, 5, 4] [2, 1, 3] [2, 1, 4] [2, 1, 5] [2, 3, 1] [2, 3, 4] [2, 3, 5] [2, 4, 1] [2, 4, 3] [2, 4, 5] [2, 5, 1] [2, 5, 3] [2, 5, 4] [3, 1, 2] [3, 1, 4] [3, 1, 5] [3, 2, 1] [3, 2, 4] [3, 2, 5] [3, 4, 1] [3, 4, 2] [3, 4, 5] [3, 5, 1] [3, 5, 2] [3, 5, 4] [4, 1, 2] [4, 1, 3] [4, 1, 5] [4, 2, 1] [4, 2, 3] [4, 2, 5] [4, 3, 1] [4, 3, 2] [4, 3, 5] [4, 5, 1] [4, 5, 2] [4, 5, 3] [5, 1, 2] [5, 1, 3] [5, 1, 4] [5, 2, 1] [5, 2, 3] [5, 2, 4] [5, 3, 1] [5, 3, 2] [5, 3, 4] [5, 4, 1] [5, 4, 2] [5, 4, 3] 60
问题3: 从m个球里(编号为1,2,3...,m)一次取n个球,其中m>n,记录取出球的编号,枚举所有的可能性。
分析:这是组合问题。因该有
种可能性。
这里,我们取m = 8, n = 4. 因此有
种可能。
代码:
import java.util.Stack; public class Test { static int cnt = 0; static Stack<Integer> s = new Stack<Integer>(); /** * 递归方法,当前已抽取的小球个数与要求抽取小球个数相同时,退出递归 * @param curnum - 当前已经抓取的小球数目 * @param curmaxv - 当前已经抓取小球中最大的编号 * @param maxnum - 需要抓取小球的数目 * @param maxv - 待抓取小球中最大的编号 */ public static void kase3(int curnum, int curmaxv, int maxnum, int maxv){ if(curnum == maxnum){ cnt++; System.out.println(s); return; } for(int i = curmaxv + 1; i <= maxv; i++){ // i <= maxv - maxnum + curnum + 1 s.push(i); kase3(curnum + 1, i, maxnum, maxv); s.pop(); } } public static void main(String[] args){ kase3(0, 0, 4, 8); System.out.println(cnt); } }
输出:
[1, 2, 3, 4] [1, 2, 3, 5] [1, 2, 3, 6] [1, 2, 3, 7] [1, 2, 3, 8] [1, 2, 4, 5] [1, 2, 4, 6] [1, 2, 4, 7] [1, 2, 4, 8] [1, 2, 5, 6] [1, 2, 5, 7] [1, 2, 5, 8] [1, 2, 6, 7] [1, 2, 6, 8] [1, 2, 7, 8] [1, 3, 4, 5] [1, 3, 4, 6] [1, 3, 4, 7] [1, 3, 4, 8] [1, 3, 5, 6] [1, 3, 5, 7] [1, 3, 5, 8] [1, 3, 6, 7] [1, 3, 6, 8] [1, 3, 7, 8] [1, 4, 5, 6] [1, 4, 5, 7] [1, 4, 5, 8] [1, 4, 6, 7] [1, 4, 6, 8] [1, 4, 7, 8] [1, 5, 6, 7] [1, 5, 6, 8] [1, 5, 7, 8] [1, 6, 7, 8] [2, 3, 4, 5] [2, 3, 4, 6] [2, 3, 4, 7] [2, 3, 4, 8] [2, 3, 5, 6] [2, 3, 5, 7] [2, 3, 5, 8] [2, 3, 6, 7] [2, 3, 6, 8] [2, 3, 7, 8] [2, 4, 5, 6] [2, 4, 5, 7] [2, 4, 5, 8] [2, 4, 6, 7] [2, 4, 6, 8] [2, 4, 7, 8] [2, 5, 6, 7] [2, 5, 6, 8] [2, 5, 7, 8] [2, 6, 7, 8] [3, 4, 5, 6] [3, 4, 5, 7] [3, 4, 5, 8] [3, 4, 6, 7] [3, 4, 6, 8] [3, 4, 7, 8] [3, 5, 6, 7] [3, 5, 6, 8] [3, 5, 7, 8] [3, 6, 7, 8] [4, 5, 6, 7] [4, 5, 6, 8] [4, 5, 7, 8] [4, 6, 7, 8] [5, 6, 7, 8] 70
相关文章推荐
- Java解决排列组合问题——深度优先遍历
- Java解决排列组合问题——深度优先遍历
- Java解决排列组合问题——深度优先遍历
- Java解决排列组合问题——深度优先遍历
- Java解决排列组合问题——深度优先遍历
- 多个数组间元素排列组合问题求解(Java实现)
- java 排列组合问题汇总
- 多个数组间元素排列组合问题求解(Java实现) 标签: 递归排列组合循环
- Flex+Java组合解决汉字或特殊符号(如&等)文件下载时的文件名乱码问题
- AC解 - 用动态规划解决一道排列组合计数问题(序关系计算)
- java实现字符串排列组合问题
- java实现字符串排列组合问题
- 字符串的排列组合问题-java
- java数组排列组合问题汇总
- 如何用itertools解决无序排列组合的问题
- C语言实现的排列组合问题的通用算法、解决方法
- 递归类型的排列组合来解决问题(一个、周期类排列组合)
- 递归解决问题的几种类型的排列(二、完整的组合安排)
- 一类排列组合问题的解决办法
- 引入进制概念解决排列组合问题