字节跳动青训营刷题笔记2| 豆包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

代码

python 复制代码
def solution(numbers):
        # 统计每个组中的奇数和偶数个数
        odd_even_count = []
        
        for group in numbers:
            odd_count = sum(1 for digit in str(group) if int(digit) % 2 == 1)
            even_count = len(str(group)) - odd_count
            odd_even_count.append((odd_count, even_count))
    
        # 动态规划:dp[i][0] 表示前i个组选出的数字和为偶数的组合数,dp[i][1] 表示前i个组选出的数字和为奇数的组合数
        dp = [[0, 0] for _ in range(len(odd_even_count) + 1)]   
        dp[0][0] = 1  # 初始状态:没有选择任何数字,和为偶数
    
        for i in range(1, len(odd_even_count) + 1):
            odd_count, even_count = odd_even_count[i - 1]
        
            # 选择偶数的数字:当前和保持不变(偶数和偶数仍为偶数,奇数和奇数也为偶数)
            dp[i][0] = dp[i - 1][0] * even_count + dp[i - 1][1] * odd_count
            # 选择奇数的数字:当前和变为奇数(偶数和奇数为奇数)
            dp[i][1] = dp[i - 1][0] * odd_count + dp[i - 1][1] * even_count
    
        return dp[len(odd_even_count)][0]  # 返回最终和为偶数的组合数

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution([123, 456, 789]) == 14)
    print(solution([123456789]) == 4)
    print(solution([14329, 7568]) == 10)

题目分析

这段代码的目的是使用 动态规划 来解决一个组合数的问题,即从多个数字组中选择一个数字,并计算这些选择的组合,使得所选数字的和为偶数的组合数。

问题的简化

我们有多个数字组(每个数字组包含一些数字),我们需要从每个数字组中选择一个数字,使得选出的数字和的总和是偶数。目标是计算出所有可能的选法,使得和为偶数的组合数。

动态规划的思路

  1. 状态定义:

    • dp[i][0] 来表示,选择前 i 个数字组中的数字时,数字和为偶数的组合数。
    • dp[i][1] 来表示,选择前 i 个数字组中的数字时,数字和为奇数的组合数。
  2. 初始状态:

    • 初始时没有选择任何数字时,和为偶数,这时候有且只有一种情况,所以 dp[0][0] = 1。也就是,选择 0 个数字时,和为偶数的组合数是 1。
  3. 状态转移: 对于每一个数字组 i,我们有两种选择:

    • 选择偶数的数字:

      • 如果我们选择一个偶数,那么不管当前的总和是偶数还是奇数,和仍然保持偶数。所以,当前选择偶数的情况会更新 dp[i][0](即和为偶数的情况)。
      • 如果之前选的和为偶数的数字组合数是 dp[i-1][0],那么选择一个偶数后,和依然是偶数。
      • 如果之前选的和为奇数的数字组合数是 dp[i-1][1],那么选择一个偶数后,和变回偶数。
      • 因此,dp[i][0] 更新的方式为:dp[i][0] = dp[i-1][0] * even_count + dp[i-1][1] * odd_count
    • 选择奇数的数字:

      • 如果我们选择一个奇数,那么当前和的奇偶性将会翻转:

        • 如果当前和为偶数,选择奇数后和变为奇数。
        • 如果当前和为奇数,选择奇数后和变回偶数。
      • 所以,更新 dp[i][1](即和为奇数的组合数):

        • 如果之前选的和为偶数的数字组合数是 dp[i-1][0],选择一个奇数后,和变为奇数。
        • 如果之前选的和为奇数的数字组合数是 dp[i-1][1],选择一个奇数后,和变为偶数。
      • 因此,dp[i][1] 更新的方式为:dp[i][1] = dp[i-1][0] * odd_count + dp[i-1][1] * even_count

  4. 最终结果:

    • 最终,dp[len(odd_even_count)][0] 存储的是选取所有数字组时,和为偶数的组合数。
相关推荐
柠檬柠檬1 小时前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记
用户967136399651 小时前
计算最小步长丨豆包MarsCodeAI刷题
青训营笔记
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刷题
青训营笔记
热的棒打鲜橙2 天前
数字分组求偶数和 | 豆包MarsCode AI刷题
青训营笔记
JinY142 天前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记