持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
1、前言
每天一个算法小练习,本篇使用Java实现。
2、题目描述
有K种颜色的小球(K<=10),每种小球有若干个,总数小于100个。现在有一个小盒子,能放N个小球(N<=8),现在要从这些小球里挑出N个小球,放满盒子。想知道有哪些挑选方式。注:每种颜色的小球之间没有差别。请按数字递增顺序输出挑选小球的所有方式。
如有3种颜色,每种颜色小球的个数分别为a:1,b:2,c:3,挑出3个小球的挑法有:003,012,021,102,111,120。
2.1、输入描述
第一行两个数字K N,分别表示小球种类数目和挑选的小球个数;
第二行开始为每种小球的数目,共K行数据。
2.2、输出描述
输出所有可行的挑选方案,按升序排列.
2.3、示例1
输入:
3 3
1
2
3
输出:
003
012
021
102
111
120
3、解题思路
3.1、递归
每种小球分别取0~max值
3.1.1、实现代码
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int k = sc.nextInt();
int n = sc.nextInt();
//记录颜色球的个数
int[] nums = new int[k];
for(int i = 0;i < k; i++){
nums[i] = sc.nextInt();
}
List<String> result = new LinkedList<>();
recursion(result,n,0,nums,"");
result.forEach(System.out::println);
}
}
/**
* 利用递归思想,深度优先遍历
* @param result
* @param target
* @param start
* @param nums
* @param s
*/
public static void recursion(List<String> result,int target,int start,int[] nums,String s){
if(target == 0 && start == nums.length){
result.add(s);
return;
}
if(start == nums.length){
return;
}
for(int i = 0;i <= Math.min(target,nums[start]);i++){
// 取当前 target 和对应球的数量中的较小值。
recursion(result,target - i,start+1,nums,s+i);
}
}
3.1.2、执行结果
3.2、for循环
采用3层for循环,分别计算出取每种球之前有几种方案,最后输出结果。
3.2.1、实现代码
/**
* 两个List嵌套,记录取球方案
*/
private static List<List<Integer>> reslut = new ArrayList<>();
private static List<String> resStr = new LinkedList<>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int k = scanner.nextInt();
int n = scanner.nextInt();
int[] colors = new int[k];
for (int i = 0; i < k; i++) {
colors[i] = scanner.nextInt();
}
testBall(colors, k, n, 0);
resStr.forEach(System.out::println);
}
}
public static void testBall(int[] colors, int k, int n, int level) {
if (k == 1) {
//只有一种方案
System.out.println(n);
return;
}
for (int i = 0; i <= colors[0]; i++) {
//初始化,第一种球的取法
reslut.add(Arrays.asList(i));
}
List<Integer> temp;
for (int i = 1; i < k; i++) {
//取哪种球
List<List<Integer>> lastTurn = reslut;
List<List<Integer>> nowTurn = new ArrayList<>();
for (int j = 0; j < lastTurn.size(); j++) {
//取第i种球之前有几种方案
for (int z = 0; z <= colors[i]; z++) {
//第i种球可以取多少个
temp = new ArrayList<>();
//取第i-1种球的第j种方案
temp.addAll(lastTurn.get(j));
//第i种球取z个
temp.add(z);
if (i == k-1) {
//取完K种球并且球的总数为N(k-1是因为第一种球初始化处理了)
if (temp.stream().reduce(0, (u1, u2)->u1 + u2) == n) {
//输出方案
print(temp, k);
}
} else {
if (temp.stream().reduce(0, (u1, u2)->u1 + u2) <= n) {
//取完第i种球之后的取球方案
nowTurn.add(temp);
}
}
}
}
reslut = nowTurn;
}
}
public static void print(List<Integer> l, int k) {
StringBuilder sb = new StringBuilder();
l.forEach(u -> sb.append(u));
for (int i = l.size(); i < k; i++) {
sb.append(0);
}
resStr.add(sb.toString());
}
3.2.1、执行结果
好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊