从m个字母中选择n个字母的所有选择,并打印
来源:互联网 发布:昆仑虚麒麟臂进阶数据 编辑:程序博客网 时间:2024/06/10 01:36
关于排列组合的数学知识,推荐阅读http://blog.csdn.net/onlyqi/article/details/8525280
[A, B, D, C]
[A, C, B, D]
[A, C, D, B]
[A, D, C, B]
[A, D, B, C]
[B, A, C, D] -- 然后是A和B交换,后面的元素递归调用。
[B, A, D, C]
[B, C, A, D]
[B, C, D, A]
[B, D, C, A]
[B, D, A, C]
[C, B, A, D]
[C, B, D, A]
[C, A, B, D]
[C, A, D, B]
[C, D, A, B]
[C, D, B, A]
[D, B, C, A]
[D, B, A, C]
[D, C, B, A]
[D, C, A, B]
[D, A, C, B]
[D, A, B, C]
我们应该牢记排列组合的数学公式,以便检验代码的输出是否正确。
在这里我把问题变化一下,可以得到3类问题:
- 打印m个字母的所有排列方式。我们常称这种排列方式为全排列,然而在数学上,称为置换substitution。
public static void subtitution(char[] s, int start, int end) {if (start == end) {System.out.println(Arrays.toString(s));} else {for (int i = start; i <= end; i++) {char temp;temp = s[start];s[start] = s[i];s[i] = temp;subtitution(s, start + 1, end);temp = s[i];s[i] = s[start];s[start] = temp;}}}
从置换这个名字我们可以得到一些灵感:就是从数组的第一个元素开始,和后面的元素依次交换。
[A, B, C, D] -- 1,首先是A和自己交换 2,后面的元素递归调用 3,将之前交换后产生的数组复原[A, B, D, C]
[A, C, B, D]
[A, C, D, B]
[A, D, C, B]
[A, D, B, C]
[B, A, C, D] -- 然后是A和B交换,后面的元素递归调用。
[B, A, D, C]
[B, C, A, D]
[B, C, D, A]
[B, D, C, A]
[B, D, A, C]
[C, B, A, D]
[C, B, D, A]
[C, A, B, D]
[C, A, D, B]
[C, D, A, B]
[C, D, B, A]
[D, B, C, A]
[D, B, A, C]
[D, C, B, A]
[D, C, A, B]
[D, A, C, B]
[D, A, B, C]
最后输出的结果应该是n的阶乘。如上例为4*3*2*1=24种。大家每次做这种题时,应使用数学公式验证结果是否正确。
- 在m个字母中选择n个字母,并打印。注意这里是组合,也就是说123和132是一个。这个在数学上称为组合combination。
组合的数学公式是. 下面算法用数学公式检验是正确的。
import java.util.Stack;public class App { public static void main(String[] args) { comb(new String[]{"A", "B", "C", "D", "E", "F", "G"}, 3); } public static void comb(String[] m, int n) { Stack<String> buf = new Stack<String>(); doComb(m, 0, n, buf); } public static void doComb(String[] m, int start, int n, Stack<String> buf) { if (m.length - start + buf.size() == n) { for(String s : buf) { System.out.print(s + ","); } for(int i = start; i < m.length; ++i) { System.out.print(m[i] + ","); } System.out.println(""); }else if (start < m.length){ buf.push(m[start]); doComb(m, start + 1, n, buf); buf.pop(); doComb(m, start + 1, n, buf); } }}
- 在m个字母中选择n个字母,并打印。这里我们变化一下,要的是排列,也就是说123和132不是一个。在数学上称为排列permutation.
现在我们就可以把问题分成两部分了:首先使用上面的方法二在m个字母中选择出n个,然后是用方法一对每种组合进行全排列就可以了。
import java.util.ArrayList;import java.util.Stack;public class App {public static ArrayList<String> al = new ArrayList<String>();public static void main(String[] args) {comb(new String[] { "A", "B", "C", "D" }, 3);}public static void comb(String[] m, int n) {Stack<String> buf = new Stack<String>();ArrayList<String> al = new ArrayList<String>();al = doComb(m, 0, n, buf);for (String s : al) {perm(s.toCharArray(),0,2);}}public static ArrayList<String> doComb(String[] m, int start, int n,Stack<String> buf) {if (m.length - start + buf.size() == n) {String x = "";for (String s : buf) {x = x + s;}for (int i = start; i < m.length; ++i) {x = x + m[i];}al.add(x);} else if (start < m.length) {buf.push(m[start]);doComb(m, start + 1, n, buf);buf.pop();doComb(m, start + 1, n, buf);}return al;}public static void perm(char[] buf, int start, int end){ if(start==end){ for(int i=0;i<=end;i++){ System.out.print(buf[i]); } System.out.println(); } else{ for(int i=start;i<=end;i++){ char temp=buf[start]; buf[start]=buf[i]; buf[i]=temp; perm(buf,start+1,end); temp=buf[start]; buf[start]=buf[i]; buf[i]=temp; } } } }
最后,如果仅需要计算有多少种可能的组合,而不需要打印,那么不论是置换,排列还是组合都很简单。我们可以直接使用数学公式计算(公式参考本文开始提到的另外一篇blog),也可以使用递归(递归解法可以参考另外一篇文章:http://blog.csdn.net/onlyqi/article/details/7536150)
下面是用递归计算组合的代码。
public class Testing { public static void main(String arg[]){ System.out.println(selector1(5,3)); } public static int selector1(int i, int j){ if(j == 1){ return i; } if(i == j){ return 1; } return selector1(i-1,j-1)+selector1(i-1,j); }}
<pre>
- 从m个字母中选择n个字母的所有选择,并打印
- 组合问题-----从字母表中选择n个字母
- 输出前M个字母中任取N个的所有组合情况
- 从M个不同的整数中,选择N个出来排列
- 从n个数中选择随机选择m个, m个数互不重复
- 小算法:从N个对象中随机选择M个
- 编程实现打印出26个字母的所有子集
- 20150915华为软件笔试题-从m个不同字母中任取n个字目的组合
- 产生n个字母
- 从m个字符选出n个的所有组合
- 选择城市,左边是按字母顺序的城市排列,右边是26个字母
- 【转载】从长度为n的数组中选择m个数的所有结果
- 使用回溯法求所有从n个元素中取m个元素的组合
- c++中生成n个m位的随机不重复字符串的一种方法(字母+数字)
- c++支持课打印若干个字母(A-N)
- Java中从m个数中随机选取n个不同的数(m>=n),并进行排序
- awk打印第一个字母
- 从长度为N的数组中找出所有M个元素组合的优化算法
- FCKeditor的配置使用及JS获取FCKeditor内容
- 享受寂寞
- SubSnoic 框架入门到提高---全程记录
- Perry Tam分享Storm8营销策略及企业文化
- eclipse 4.2反编译插件jad安装
- 从m个字母中选择n个字母的所有选择,并打印
- 从实例来理解OOP思想、工厂模式和重构
- 概率生成器-算法
- 图标控件Highcharts使用指南
- 进程、线程区别
- JAVA递归
- Vim入门(六):行的光标移动
- COLORREF 、 RGB、
- SetConsoleCtrlHandler函数