题目简意
题目要求我们从一个由1到9组成的数字集合中,随机将这些数字分成多组,然后从每组中按顺序取出一个数字,组成一个新的数字。我们需要计算出所有可能的组合中,新数字的各位数字之和为偶数的组合数量。
输入输出
- 输入:多个整型数字,数字之间用一个空格分隔。
- 输出:一个整数,表示符合条件的组合数量。
样例分析
- 样例1:输入
123 456 789
,输出14
。表示从每组中按顺序取出一个数字,组成的新数字的各位数字之和为偶数的组合有14种。 - 样例2:输入
123456789
,输出4
。表示从每组中按顺序取出一个数字,组成的新数字的各位数字之和为偶数的组合有4种。 - 样例3:输入
14329 7568
,输出10
。表示从每组中按顺序取出一个数字,组成的新数字的各位数字之和为偶数的组合有10种。
数据范围
- 数字范围:1到9。
- 分组数量:至少1组。 好的,下面是具体的解题思路,结合题目要求和当前代码进行详细解析:
解题思路
-
理解题目:
- 题目要求我们从每组数字中按顺序取出一个数字,组成一个新的数字,使得新数字的各位数字之和为偶数。
- 输入是多个整型数字,数字之间用一个空格分隔。
- 输出是一个整数,表示符合条件的组合数量。
-
数据结构选择:
- 使用一个二维列表
groups
来存储每组数字。 - 使用一个列表
combinations
来存储所有可能的组合。
- 使用一个二维列表
-
算法步骤:
- 数据转换:将输入的数字字符串转换为二维列表
groups
。 - 递归生成组合:使用递归方法
generateCombinations
生成所有可能的组合。 - 检查组合和:使用
isSumEven
方法检查每个组合的各位数字之和是否为偶数。 - 统计结果:统计符合条件的组合数量并返回。
- 数据转换:将输入的数字字符串转换为二维列表
个人详细思考解题步骤
1. 数据转换
将输入的数字字符串转换为二维列表 groups
。每个数字字符串被转换为一个列表,所有列表构成一个二维列表。
List<List<Integer>> groups = new ArrayList<>();
for (int num : numbers) {
List<Integer> group = new ArrayList<>();
String numStr = String.valueOf(num);
for (char c : numStr.toCharArray()) {
group.add(Character.getNumericValue(c));
}
groups.add(group);
}
2. 递归生成组合
使用递归方法 generateCombinations
生成所有可能的组合。递归的基本思想是从当前组中选择一个数字,然后递归处理下一组,直到所有组都处理完毕。
private static void generateCombinations(List<List<Integer>> groups, int index, List<Integer> current, List<List<Integer>> combinations) {
if (index == groups.size()) {
combinations.add(new ArrayList<>(current));
return;
}
for (int num : groups.get(index)) {
current.add(num);
generateCombinations(groups, index + 1, current, combinations);
current.remove(current.size() - 1);
}
}
3. 检查组合和
使用 isSumEven
方法检查每个组合的各位数字之和是否为偶数。
private static boolean isSumEven(List<Integer> combination) {
int sum = 0;
for (int num : combination) {
sum += num;
}
return sum % 2 == 0;
}
4. 统计结果
统计符合条件的组合数量并返回。
int count = 0;
for (List<Integer> combination : combinations) {
if (isSumEven(combination)) {
count++;
}
}
return count;
代码框架
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int[] numbers) {
// 将输入的数字字符串转换为二维数组
List<List<Integer>> groups = new ArrayList<>();
for (int num : numbers) {
List<Integer> group = new ArrayList<>();
String numStr = String.valueOf(num);
for (char c : numStr.toCharArray()) {
group.add(Character.getNumericValue(c));
}
groups.add(group);
}
// 使用递归生成所有可能的组合
List<List<Integer>> combinations = new ArrayList<>();
generateCombinations(groups, 0, new ArrayList<>(), combinations);
// 统计符合条件的组合数量
int count = 0;
for (List<Integer> combination : combinations) {
if (isSumEven(combination)) {
count++;
}
}
return count;
}
// 递归生成所有可能的组合
private static void generateCombinations(List<List<Integer>> groups, int index, List<Integer> current, List<List<Integer>> combinations) {
if (index == groups.size()) {
combinations.add(new ArrayList<>(current));
return;
}
for (int num : groups.get(index)) {
current.add(num);
generateCombinations(groups, index + 1, current, combinations);
current.remove(current.size() - 1);
}
}
// 检查组合的各位数字之和是否为偶数
private static boolean isSumEven(List<Integer> combination) {
int sum = 0;
for (int num : combination) {
sum += num;
}
return sum % 2 == 0;
}
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);
}
}
知识总结:
1.递归与回溯
递归和回溯是解决组合问题的常用方法。递归通过不断调用自身来解决问题,而回溯则是在递归的基础上,通过撤销上一步的操作来探索所有可能的解。在本题中,我们使用递归来生成所有可能的组合,并通过回溯来撤销上一步的操作。
2.数据结构
- 列表:列表是Java中常用的动态数组,可以方便地添加和删除元素。在本题中,我们使用列表来存储每组数字和所有可能的组合。
- 二维数组:二维数组可以用来存储多组数据,每组数据可以是一个列表。在本题中,我们使用二维数组来存储每组数字。
3.算法优化
- 剪枝:在递归过程中,可以通过剪枝来减少不必要的计算。例如,如果当前组合的和已经为奇数,则可以直接返回,不再继续递归。
- 动态规划:对于更复杂的问题,可以使用动态规划来优化算法。动态规划通过存储中间结果来避免重复计算,从而提高效率。
代码实现
- 数据转换:将输入的数字字符串转换为二维数组。
- 递归生成组合:使用递归生成所有可能的组合。
- 检查组合和:检查每个组合的各位数字之和是否为偶数。
- 统计结果:统计符合条件的组合数量并返回。
总结
本题通过递归和回溯的方法生成所有可能的组合,并通过检查组合的各位数字之和是否为偶数来统计符合条件的组合数量。递归和回溯是解决组合问题的常用方法,而列表和二维数组则是常用的数据结构。通过剪枝和动态规划等优化方法,可以进一步提高算法的效率。