青训营X豆包MarsCode 技术训练营3| 豆包MarsCode AI 刷题

25 阅读9分钟

问题描述

小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

题目解析

思路

这道题目的核心思路是通过递归的方式去遍历所有可能的分组选数组合,然后判断每种组合所构成的新数各位数字之和是否为偶数,统计满足条件的组合数量。

具体来说,首先将输入的整数数组中的每个整数转换为字符串形式,方便后续对每个数字组里的单个数字进行操作。接着,从第一个数字组开始,依次尝试选择其中的每个数字,每选择一个数字后,就带着当前已选数字的和进入下一个数字组继续选择数字,这个过程不断重复,直到遍历完所有的数字组。当完成了对所有数字组的选择后,也就是到达了递归的边界(index == numberGroups.length ),此时判断最终的数字和是否为偶数,如果是偶数则表示找到了一种满足条件的组合,返回 1,否则返回 0。通过这样不断地递归探索和统计,最终得到满足各位数字之和为偶数的组合数量。

例如,对于输入 [123, 456, 789] ,先从第一个数字组 “123” 中选数字,假设选了 1,然后带着这个 1 进入第二个数字组 “456” 继续选,选完后再进入第三个数字组 “789” 选,选完后判断这三个数字之和是否为偶数,是则计数加 1,然后回溯到前面的选择步骤,换其他数字再重复这个过程,把所有可能的情况都遍历一遍,从而统计出符合条件的组合数量为 14 种。

public class Main {
public static int solution(int[] numbers) {
    // 将每个数字转换为字符串以便处理每个数字组
    String[] numberGroups = new String[numbers.length];
    for (int i = 0; i < numbers.length; i++) {
        numberGroups[i] = String.valueOf(numbers[i]);
    }

    return countEvenSumCombinations(numberGroups, 0, 0);
}

private static int countEvenSumCombinations(String[] numberGroups, int index, int currentSum) {
    if (index == numberGroups.length) {
        return (currentSum % 2 == 0) ? 1 : 0;
    }

    int count = 0;
    for (char num : numberGroups[index].toCharArray()) {
        count += countEvenSumCombinations(numberGroups, index + 1, currentSum + (num - '0'));
    }

    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);
}
}

代码详解

在 solution 方法中,先是通过一个循环将输入的整数数组 numbers 中的每个元素都转换为字符串,存储到 numberGroups 数组中,方便后续处理。然后调用 countEvenSumCombinations 方法开始递归统计过程。

在 countEvenSumCombinations 方法里,首先判断递归是否到达边界,也就是 index 是否等于 numberGroups 的长度,如果相等了,就通过判断 currentSum 是否能被 2 整除来确定是否满足各位数字之和为偶数的条件,满足则返回 1,不满足返回 0。

若还没到达边界,就进入循环,这个循环会遍历当前数字组(numberGroups[index] )里的每个字符(也就是每个数字),对于每个数字,将其转换为对应的整数值(通过 num - '0' 操作)并累加到 currentSum 中,然后带着更新后的 currentSum 和下一个 index (即 index + 1 )继续递归调用 countEvenSumCombinations 方法,把每次递归返回的结果累加到 count 变量中,最后返回这个 count ,它就代表了满足条件的组合数量。

在 main 方法中,给出了几个不同输入的测试样例,通过调用 solution 方法并对比输出结果与预期值是否一致,来验证代码的正确性,这样能帮助我们及时发现代码在处理不同规模、不同情况输入时可能存在的逻辑问题。

知识总结

通过刷这道题,我们收获了不少重要知识点以及有了更深的理解。

一是对递归思想的进一步掌握。递归在编程中是一种非常强大且常用的解决问题的方法,它通过将大问题逐步分解为相似的小问题,直到小问题可以直接解决(也就是到达递归边界),然后再层层回溯汇总结果。本题中,通过不断递归地去选择数字并判断和的奇偶性,很好地体现了这一思想。我们要理解递归函数的调用过程、参数传递以及边界条件的设定,这对于解决很多具有重复子结构的复杂问题很关键。

二是对字符与数字转换以及字符串处理的运用更加熟练。将整数转换为字符串方便对每个数位进行操作,以及把字符串中的字符再转换回数字参与运算,这些操作在实际编程中处理数字相关的复杂逻辑时经常会用到。比如在密码验证、数字格式处理等场景中,都需要灵活地进行字符和数字之间的转换以及字符串的遍历、截取等操作。

对于入门的同学,我的学习建议是,首先要扎实学习递归的基础概念,多去看一些简单的递归示例,比如计算阶乘、斐波那契数列等,理解递归是如何通过函数自身调用来解决问题的,然后自己动手去写一写简单的递归代码,体会递归的执行流程和边界条件的重要性。对于字符与数字的转换以及字符串处理,要多做一些针对性的小练习,比如给定一个数字,通过不同方式将其转换为字符串并进行各种操作,再将字符串还原为数字等,通过实践来加深理解和掌握这些操作的细节。

学习计划

结合刷题功能,以下是我总结的高效学习方法。

制定刷题计划

我们可以按照知识点和难度层次来制定刷题计划。对于像本题涉及的递归和字符串处理相关的题目,可以先从简单的只运用单一知识点的题目开始刷起。比如先刷一些仅考查递归基础概念,像简单的递归计算数学表达式的题目,掌握好递归的基本运用后,再去做像本题这样结合了字符串处理以及复杂逻辑判断的题目。每周可以给自己设定一个合理的刷题量,比如每周刷 8 - 10 道题,根据题目难度合理分配时间,较难的题目可以多花些时间深入分析和调试代码,确保每道题都能真正理解透彻,不断积累解题经验,逐步提升能力。

利用错题进行针对性学习

错题是我们提升编程能力的宝贵资源。当遇到做错的题目时,要仔细分析做错的原因。如果是对递归的理解出现偏差,比如递归边界设置错误或者递归调用逻辑混乱,那就重新回顾递归的相关知识,对照正确答案的递归结构,一步一步分析自己的代码哪里出了问题,并且可以画递归调用树等辅助工具来帮助自己理解正确的递归流程。要是字符与数字转换或者字符串处理方面的错误,就再次复习相关的语法和操作方法,做一些类似的针对性练习进行巩固,比如对字符串中字符的提取、拼接以及数字和字符相互转换的专项练习,把错题中暴露的知识点漏洞补上,避免下次再犯同样的错误。

工具运用

要想将 AI 刷题功能与其他学习资源相结合,达到更好的学习效果,可以从以下方面入手。

一方面,结合线上的编程课程学习。很多在线编程课程都有系统讲解递归、字符串处理等知识点的章节,还有丰富的案例演示和课后练习。在刷题之前,如果对相关知识点掌握不扎实,就可以去对应的课程里进行学习巩固,跟着老师的思路和示例代码深入理解概念和运用方法。在刷题过程中遇到难题时,也可以参考课程里类似问题的解法思路,拓宽自己的思维方式,然后再尝试用自己的方法去解决题目,这样能更好地吸收知识并且提高解题能力。

另一方面,利用编程论坛和社区也是不错的选择。在论坛上可以搜索到其他程序员对于类似本题这种涉及递归和字符串处理问题的讨论,看看大家分享的不同解法思路、遇到的问题以及解决办法等,从中获取灵感和经验。同时,自己也可以把刷题过程中遇到的疑惑或者独特的解题思路发布出来,与大家交流互动,通过他人的反馈来进一步完善自己的知识体系和解题方法,而且在交流过程中还能结交志同道合的学习伙伴,一起互相鼓励、共同进步。