问题描述 小M面对一组从 1 到 9 的数字,这些数字被分成多个小组,并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。
numbers: 一个由多个整数字符串组成的列表,每个字符串可以视为一个数字组。小M需要从每个数字组中选择一个数字。 例如对于[123, 456, 789],14个符合条件的数为:147 149 158 167 169 248 257 259 268 347 349 358 367 369。
测试样例 样例1:
输入:numbers = [123, 456, 789] 输出:14
样例2:
输入:numbers = [123456789] 输出:4
样例3:
输入:numbers = [14329, 7568] 输出:10
以下是对该问题的详细分析:
一、问题理解
我们有数字 1 到 9,要将它们分成多个小组,然后从每个小组中选一个数字组成新数,且要求新数的各位数字之和为偶数。关键在于找出满足数字之和为偶数这一条件的所有可能分组及选择方式。
二、整体思路
为了计算满足条件的分组和选择方法数,我们可以通过分析数字的奇偶性特征,结合组合数学的相关知识来逐步推导。
三、数字的奇偶性分析
-
在 1 到 9 这 9 个数字中,有 5 个奇数(1、3、5、7、9)和 4 个偶数(2、4、6、8)。
-
一个数各位数字之和为偶数的情况有两种:
- 所选数字全是偶数,因为偶数之和为偶数。
- 所选数字中有偶数个奇数,因为偶数个奇数相加为偶数,再加上若干偶数后总和依然为偶数。
四、计算分组和选择方法
-
全选偶数的情况:
- 只有一种分组方式,就是将 4 个偶数各自分为一组(共 4 组)。
- 从这 4 组中各选一个数字组成新数,选择方法有:每个组都只有 1 种选法(选那个唯一的偶数),所以总的选择方法为 种。
-
有偶数个奇数的情况:
-
选 2 个奇数和若干偶数:
- 先考虑选 2 个奇数的分组情况,从 5 个奇数中选 2 个奇数的组合数为 种分组方式(即将选出来的 2 个奇数作为一组,剩下的 3 个奇数各自为一组,再加上 4 个偶数各自为一组,总共 8 组)。
- 对于选偶数,每个偶数都有 1 种选法,有 4 个偶数,所以选偶数的方法有 种。而选 2 个奇数那一组的选法就是从这一组的 2 个奇数中选 1 个,有 2 种选法。所以这种情况下总的选择方法为 种。
-
选 4 个奇数和若干偶数:
- 从 5 个奇数中选 4 个奇数的组合数为 种分组方式(即将选出来的 4 个奇数作为一组,剩下的 1 个奇数自己为一组,再加上 4 个偶数各自为一组,总共 6 组)。
- 选偶数的方法还是 种。选 4 个奇数那一组的选法就是从这一组的 4 个奇数中选 1 个,有 4 种选法。所以这种情况下总的选择方法为 种。
-
五、汇总结果
将上述各种情况的方法数相加,可得满足条件的不同分组和选择方法总数为: 种。
综上所述,通过对数字奇偶性的分析以及运用组合数学的知识,我们得出有 41 种不同的分组和选择方法可以使得组成的新数各位数字之和为偶数。
计算从1到9的数字中选2个奇数和若干偶数组成各位数字之和为偶数的新数的方法数
选4个奇数的情况下,有多少种分组方式和选择方法?
若允许数字重复选择,那么满足条件的分组和选择方法有多少种? Java代码 (含注释&要点)
import java.util.ArrayList; import java.util.List;
public class Main { public static int solution(int[] numbers) { // 思路: // ① 将每组数字拆成单个数字 // ② 记录每个数字的奇偶性 // ③ 递归/回溯,从每个数字组中选择一个数字,并检查各数之和是否为偶数 // ④ 计算结果:递归的终止条件中,检查当前组合的各数之和是否为偶数 int n = numbers.length; List<List> digits = new ArrayList<>(); for(int i = 0;i < n;i++){ List group = new ArrayList<>(); char[] charArr = Integer.toString(numbers[i]).toCharArray(); //将数字转为字符数组
for(int j = 0;j < charArr.length;j++){
group.add(charArr[j]-'0');
}
digits.add(group);
}
return backtrack(digits, 0, 0);
}
// 组合选择,用递归、回溯的方法,从数字组中选择一个数字,并检查各位之和是否为偶数
private static int backtrack(List<List<Integer>> digits, int index, int currentSum){
// 终止条件:若已选择了所有数字组
if(index == digits.size()) {
return currentSum % 2 == 0 ? 1 : 0;
}
int count = 0;
for(int num : digits.get(index)){ // 增强for循环;List特有方法get、set、add、remove
// 递归调用,选择下一个数字组中的数字
count += backtrack(digits, index+1, currentSum + num);
}
return count;
}
public static void main(String[] args) {
System.out.println(solution(new int[]{123, 456, 789}) == 14);
System.out.println(solution(new int[]{123456789}) == 4);
System.out.println(solution(new int[]{14329, 7568}) == 10);
}
}