程序算术题-2
- 输出所有组合
- 逻辑
- 实例
- 代码
- 输出所有排列
- 逻辑
- 实例
- 代码
输出所有组合
计算一组数字按n位数组合的所有组合。
逻辑
/*** @param stringBuilder 用于组合的拼接* @param list 组合数序列* @param level 目前位数* @param exceptedLevel 组合期待位数*/
为了去匹配更多的组合计算题目,方法没有去固定多少位数的组合,可以自由填入指定。参数exceptedLevel代表组合的位数,参数level代表现在组合拼接达到的位数。方法也是开放自由输入用于组合的数字,并且通过Arrays封装成List序列,用于后面的方法取值。方法执行数字合成组合的操作是通过StringBuilder完成组合的拼接,并最终输出。
// 过滤重复的数字
Arrays.stream(args).distinct().collect(Collectors.toList())
由于组合是不存在重复数字,这里会使用Arrays.stream(args).distinct()方法对输入数字序列进行重复数字的过滤,最后用collect方法把数组转化成数字序列。方便后面的方法操作。
public static void combine(StringBuilder stringBuilder, List<String> list, int level, int exceptedLevel) {for (int i = 0; i < list.size(); i++) {StringBuilder builder = stringBuilder != null ? new StringBuilder(stringBuilder) : new StringBuilder();builder.replace(level - 1, level, list.get(i));if (level == exceptedLevel) {System.out.println(builder);continue;}ArrayList<String> arrayList = new ArrayList<>(list);arrayList.remove(i);combine(builder, arrayList, level + 1, exceptedLevel);}}
这里采用了递归的方式去逐个位数拼接,当目前位数达到所期待的组合位数level == exceptedLevel会进行单个组合的递归结束操作,这个组合会不再递归拼接,方法将组合输出,这样子就完成了一个组合的拼接,然后continue,继续开始下一个组合的拼接。
组合没有重复的数字,方法调用了序列的remove方法将已经进入组合的数字移除,避免出现数字的重复,并且为每一个组合创建一个源数字序列List list的副本,避免各个组合间所需拼接的数字源因为源数字序列remove导致的缺失。
实例
有无序的4,2,3,1,1个五个数字,去组成互不相同且无重复数字的三位数组合,都是多少?
/*** 互不相同,无重复数字的排列* arg[0...(n-1)] 可用于排列的数* arg[n] 排列数的位数*/public static void main(String[] args) {combine(null, Arrays.asList(args), 1, 3);}
结果如下
423
421
432
431
412
413
243
241
234
231
214
213
342
341
324
321
314
312
142
143
124
123
134
132
代码
查看组合计算题的代码
输出所有排列
计算一组数字按n位数排列的所有排列。
逻辑
/*** @param stringBuilder 用于排列的拼接* @param list 排列数序列* @param level 目前位数* @param exceptedLevel 排列期待位数*/
为了去匹配更多的排列计算题目,方法没有去固定多少位数的排列,可以自由填入指定。参数exceptedLevel代表排列的位数,参数level代表现在排列拼接达到的位数。方法也是开放自由输入用于排列的数字,并且通过Arrays封装成List序列,用于后面的方法取值。方法执行数字合成排列的操作是通过StringBuilder完成排列的拼接,并最终输出。
// 过滤重复数字List<String> list = Arrays.stream(args).distinct().collect(Collectors.toList());// 排序list.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {Integer s1 = Integer.valueOf(o1);Integer s2 = Integer.valueOf(o2);return s1 < s2 ? -1 : s1 == s2 ? 0 : 1;}});arrange(null, list, 1, 3);
由于排列是有序的,并且不存在重复数字,这里同样使用了Arrays.stream(args).distinct()方法对输入数字序列进行重复数字的过滤,以及用collect方法把数组转化成数字序列,然后再调用list.sort方法对序列进行排序,有序的序列更方便于后面的合成排列操作,它不需要重复为合成的排列进行排序操作,合成的时候已经是一个有序的排列。
public static void arrange(StringBuilder stringBuilder, List<String> list, int level, int exceptedLevel) {for (int i = 0; i < list.size(); i++) {StringBuilder builder = stringBuilder != null ? new StringBuilder(stringBuilder) : new StringBuilder();builder.replace(level - 1, level, list.get(i));if (level == exceptedLevel) {System.out.println(builder);continue;}arrange(builder, list.subList(i + 1, list.size()), level + 1, exceptedLevel);}}
这里同样是采用了递归的方式去逐个位数拼接,当目前位数达到所期待的排列位数level == exceptedLevel会进行单个排列的递归结束操作,这个排列会不再递归拼接,方法将排列输出,这样子就完成了一个排列的拼接,然后continue,继续开始下一个排列的拼接。
排列没有重复的数字,并且有排序,由于传入的List list已经是一个有序序列,这里可以通过传入排除了已入排列的数字的子序列list.subList(i + 1, list.size())来避免出现数字的重复,并且subList方法会生成一个新的序列,不影响到源数据序列,这样子就避免了各个排列间数字源的缺失。
实例
有无序的4,2,3,1,1个五个数字,去组成互不相同且无重复数字的三位数排列,都是多少?
/*** 互不相同,无重复数字的组合* arg[0...(n-1)] 可用于组合的数* arg[n] 组合数的位数*/public static void main(String[] args) {arrange(null, new ArrayList<String>(Arrays.asList(args)), 1, 3);}
结果如下
123
124
134
234
代码
查看排列计算题的代码