数字分组求偶数和 | 豆包MarsCode AI刷题

问题描述

小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

使用MarsCode AI辅助解题的过程

使用MarsCode AI

  • 思路提示:先看看MarsCode AI提供的初步思路
markdown 复制代码
### 问题理解

我们需要从每个数字组中选择一个数字,使得这些数字组成的新的数的各位数字之和为偶数。

### 数据结构选择

1.  **数字组列表**:输入是一个由多个整数字符串组成的列表,每个字符串可以视为一个数字组。
1.  **选择结果**:我们需要记录从每个数字组中选择一个数字的所有可能组合。

### 算法步骤

1.  **遍历每个数字组**:对于每个数字组,我们需要遍历其中的每个数字。
1.  **组合选择**:从每个数字组中选择一个数字,并记录这些选择的组合。
1.  **检查和的奇偶性**:对于每个组合,计算其各位数字之和,并检查是否为偶数。
1.  **统计符合条件的组合数量**:统计所有符合条件的组合数量

### 伪代码框架
public class Main {
    public static int solution(int[] numbers) {
        // 初始化符合条件的组合数量
        int count = 0;
        
        // 遍历每个数字组
        for (int group : numbers) {
            // 将数字组转换为字符串
            String groupStr = String.valueOf(group);
            
            // 遍历数字组中的每个数字
            for (char digitChar : groupStr.toCharArray()) {
                int digit = Character.getNumericValue(digitChar);
                
                // 在这里处理每个数字的选择
                // 需要记录当前组合的数字和
                // 并检查和的奇偶性
            }
        }
        
        // 返回符合条件的组合数量
        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);
    }
}
  • 回溯法指导:看完题目和MarsCode AI的提示,我想到了回溯,直接问回溯怎么做
csharp 复制代码
回溯法是一种非常适合解决组合问题的算法。我们可以使用回溯法来遍历所有可能的组合,并检查每个组合的各位数字之和是否为偶数。

### 解题思路

1. **回溯函数**:定义一个回溯函数,用于递归地从每个数字组中选择一个数字,并记录当前组合的数字和。
2. **检查和的奇偶性**:在每次选择一个数字后,检查当前组合的数字和是否为偶数。
3. **递归终止条件**:当所有数字组都被选择完毕时,检查当前组合是否符合条件。

### 伪代码框架

public class Main {
    public static int solution(int[] numbers) {
        // 初始化符合条件的组合数量
        int count = 0;
        
        // 调用回溯函数
        backtrack(numbers, 0, 0, count);
        
        // 返回符合条件的组合数量
        return count;
    }

    // 回溯函数
    private static void backtrack(int[] numbers, int index, int currentSum, int count) {
        // 如果已经遍历完所有数字组
        if (index == numbers.length) {
            // 检查当前组合的数字和是否为偶数
            if (currentSum % 2 == 0) {
                count++;
            }
            return;
        }
        
        // 将当前数字组转换为字符串
        String groupStr = String.valueOf(numbers[index]);
        
        // 遍历当前数字组中的每个数字
        for (char digitChar : groupStr.toCharArray()) {
            int digit = Character.getNumericValue(digitChar);
            
            // 递归调用回溯函数,选择下一个数字组
            backtrack(numbers, index + 1, currentSum + digit, 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);
    }
}

### 关键步骤

1. **回溯函数**:`backtrack` 函数用于递归地选择每个数字组中的一个数字,并记录当前组合的数字和。
2. **递归终止条件**:当 `index` 等于 `numbers.length` 时,表示所有数字组都被选择完毕,检查当前组合的数字和是否为偶数。
3. **递归调用**:在每次选择一个数字后,递归调用 `backtrack` 函数,选择下一个数字组。

你可以根据这个框架继续完善代码,如果有具体问题,可以继续提问。
  • 逐步引导:当发现代码运行结果不理想时,看看代码是否有比较明显的错误,发现count变量作为参数没有起到累加的效果,让MarsCode AI修改,提问"Mcount的位置是不是有问题"。
markdown 复制代码
是的,`count` 的位置确实有问题。在回溯函数中,`count` 应该是一个引用传递的变量,以便在递归调用中正确地累加符合条件的组合数量。

### 修改思路

1.  **使用引用传递**:将 `count` 作为参数传递给回溯函数,并在递归调用中累加符合条件的组合数量。
2.  **使用可变对象**:可以使用一个可变对象(如数组)来存储 `count`,以便在递归调用中正确地累加。

public class Main {
    public static int solution(int[] numbers) {
        // 初始化符合条件的组合数量
        int[] count = new int[1]; // 使用数组来存储 count,以便在递归中修改
        
        // 调用回溯函数
        backtrack(numbers, 0, 0, count);
        
        // 返回符合条件的组合数量
        return count[0];
    }

    // 回溯函数
    private static void backtrack(int[] numbers, int index, int currentSum, int[] count) {
        // 如果已经遍历完所有数字组
        if (index == numbers.length) {
            // 检查当前组合的数字和是否为偶数
            if (currentSum % 2 == 0) {
                count[0]++; // 累加符合条件的组合数量
            }
            return;
        }
        
        // 将当前数字组转换为字符串
        String groupStr = String.valueOf(numbers[index]);
        
        // 遍历当前数字组中的每个数字
        for (char digitChar : groupStr.toCharArray()) {
            int digit = Character.getNumericValue(digitChar);
            
            // 递归调用回溯函数,选择下一个数字组
            backtrack(numbers, index + 1, currentSum + digit, 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);
    }
}

## 提问:改成类变量会不会更方便

是的,将 `count` 改为类变量会更方便,因为这样可以避免在递归调用中传递参数。

### 修改思路

1.  **将 `count` 改为类变量**:在类中定义一个静态变量 `count`,用于存储符合条件的组合数量。
1.  **在回溯函数中直接累加 `count`**:在回溯函数中直接累加 `count`,而不需要传递参数。

### 修改后的代码

public class Main {
    // 定义类变量 count,用于存储符合条件的组合数量
    private static int count = 0;

    public static int solution(int[] numbers) {
        // 初始化 count
        count = 0;
        
        // 调用回溯函数
        backtrack(numbers, 0, 0);
        
        // 返回符合条件的组合数量
        return count;
    }

    // 回溯函数
    private static void backtrack(int[] numbers, int index, int currentSum) {
        // 如果已经遍历完所有数字组
        if (index == numbers.length) {
            // 检查当前组合的数字和是否为偶数
            if (currentSum % 2 == 0) {
                count++; // 累加符合条件的组合数量
            }
            return;
        }
        
        // 将当前数字组转换为字符串
        String groupStr = String.valueOf(numbers[index]);
        
        // 遍历当前数字组中的每个数字
        for (char digitChar : groupStr.toCharArray()) {
            int digit = Character.getNumericValue(digitChar);
            
            // 递归调用回溯函数,选择下一个数字组
            backtrack(numbers, index + 1, currentSum + digit);
        }
    }

    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. 检查和的奇偶性:每当选择完所有数字组后,我们需要检查当前组合的和是否为偶数。
  3. 递归终止条件:当遍历完所有数字组时,进行和的检查。
相关推荐
柠檬柠檬1 小时前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记
用户967136399651 小时前
计算最小步长丨豆包MarsCodeAI刷题
青训营笔记
用户529757993547217 小时前
字节跳动青训营刷题笔记2| 豆包MarsCode AI刷题
青训营笔记
clearcold1 天前
浅谈对LangChain中Model I/O的见解 | 豆包MarsCode AI刷题
青训营笔记
夭要7夜宵1 天前
【字节青训营】 Go 进阶语言:并发概述、Goroutine、Channel、协程池 | 豆包MarsCode AI刷题
青训营笔记
用户336901104442 天前
数字分组求和题解 | 豆包MarsCode AI刷题
青训营笔记
dnxb1232 天前
GO语言工程实践课后作业:实现思路、代码以及路径记录 | 豆包MarsCode AI刷题
青训营笔记
用户916357440952 天前
AI刷题-动态规划“DNA序列编辑距离” | 豆包MarsCode AI刷题
青训营笔记
JinY142 天前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记