青训营x豆包MarsCode 技术训练营刷题-数字分组求偶数和 | 豆包MarsCode AI刷题

117 阅读3分钟

问题

题目列表第四道:数字分组求偶数和,难度为易

问题描述

小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 之间,因此可以直接处理每个字符串中的字符。面对这种问题,我首先想到的是递归实现dfs去遍历所有可能的选择组合,再对于每一种组合进行条件判断。

具体实现

理清思路后,实现起来也并不复杂。dfs函数模版大致可以分成“判断递归是否结束”,“判断是否剪枝”和“递归扩展”这几个部分。在递归扩展的部分则可能进行遍历,修改标记,递归调用自身,还原标记等操作。在写递归参数和返回值时比较容易出错,必须牢记各参数的含义和边界。

对于这道题而言,可以首先写一个函数f判断传入的字符串每个数位之和是否为偶数,在dfs判断结束条件时用。dfs函数的参数可以传遍历到第几个数字组(index)和当前已选择的数字组成的字符串(current_digits),起点时index为0,current_digit为空,返回值为满足题目条件的组合计数count。在判断递归结束时,如果index等于数字组的个数,那么表示已经遍历完最后一个数字组,使用f判断其是否符合要求,根据判断的结果返回0或1。在递归部分,先设置计数count为0,用digit遍历(选择)index对应的数字组里的数字,那么就有count+=dfs(index+1,current_digits+digit)。完整代码如下。

def is_even_sum(digits):
    return sum(int(digit) for digit in digits) % 2 == 0

def dfs(index, current_digits):
    if index == len(numbers):
        if is_even_sum(current_digits):
            return 1
        return 0

    count = 0
    for digit in str(numbers[index]):
        count += dfs(index + 1, current_digits + digit)
    return count

return dfs(0, "")

结语

通过这道题,我们对dfs的含义和写法有了更深刻的理解,希望在接下来的刷题中能继续挑战更难的题目,进一步领悟回溯算法的精髓。