青训营刷题笔记:数字分组与选择问题
问题描述
小M面对一个包含多组数字的列表,需要从每组中选择一个数字组成一个新数,并要求这个新数的各位数字之和为偶数。任务是计算出满足条件的选择方法总数。
分析思路
要满足数字之和为偶数,需统计每组中奇数和偶数的数量,并通过组合推算满足条件的方案总数。
-
初始化状态:
假设开始时没有选任何数字,视为一个"空组合"。空组合的数字和为 0(偶数),因此初始even_count = 1,odd_count = 0。 -
遍历每组数字:
对于每一组数字,统计其中奇数 (current_odd) 和偶数 (current_even) 的数量。 -
更新组合状态:
当前选择对整体偶奇状态的影响如下:- 新的偶数组合数:
由之前的偶数组合数搭配当前偶数,或奇数组合数搭配当前奇数得到。 - 新的奇数组合数:
由之前的偶数组合数搭配当前奇数,或奇数组合数搭配当前偶数得到。 公式如下:
new_even_count = even_count * current_even + odd_count * current_odd new_odd_count = even_count * current_odd + odd_count * current_even - 新的偶数组合数:
-
最终结果:
所有组合中,满足条件的方案数即为最终even_count。
代码实现
def solution(numbers):
# 初始化偶数和奇数的组合数
even_count, odd_count = 1, 0 # 初始状态:一个空集,和为偶数
# 遍历每个数字组
for group in numbers:
current_even, current_odd = 0, 0
# 统计该数字组中奇数和偶数的数量
for digit in str(group):
if int(digit) % 2 == 0:
current_even += 1
else:
current_odd += 1
# 更新组合的状态
new_even_count = even_count * current_even + odd_count * current_odd
new_odd_count = even_count * current_odd + odd_count * current_even
even_count, odd_count = new_even_count, new_odd_count
# 返回最后的偶数组合数
return even_count
# 测试样例
if __name__ == "__main__":
print(solution([123, 456, 789]) == 14) # 输出 True
print(solution([123456789]) == 4) # 输出 True
print(solution([14329, 7568]) == 10) # 输出 True
测试样例
-
样例1
输入:numbers = [123, 456, 789]
分析:- 第一组:奇数 1, 3,偶数 2 → 奇数 2 个,偶数 1 个。
- 第二组:奇数 5,偶数 4, 6 → 奇数 1 个,偶数 2 个。
- 第三组:奇数 7, 9,偶数 8 → 奇数 2 个,偶数 1 个。
输出:14
-
样例2
输入:numbers = [123456789]
分析:奇数 5 个,偶数 4 个。
输出:4 -
样例3
输入:numbers = [14329, 7568]
分析:- 第一组:奇数 3 个,偶数 2 个。
- 第二组:奇数 3 个,偶数 1 个。
输出:10
总结
本题利用动态规划的思想,通过记录奇偶组合状态的转移,避免暴力穷举所有组合,降低了计算复杂度。核心难点在于推导偶奇状态转移公式,解决过程也体现了数学分析与编程实现的结合。数字分组与选择问题总结
本题的目标是从多个数字组中选择数字组成一个新数,使其各位数字之和为偶数,并计算符合条件的组合方式数量。核心考点是奇偶性质对数字和的影响,以及如何通过动态规划思想高效计算结果。
解题思路
-
奇偶性质分析:
一个数的各位数字之和为偶数,当且仅当选择的数字中奇数的个数为偶数。因此,问题可以转化为统计选择数字后奇数总个数为偶数的方案数。 -
动态规划状态转移:
使用两个变量even_count和odd_count分别记录当前组合中奇数和偶数的方案数。-
初始状态:组合为空,和为偶数,
even_count = 1,odd_count = 0。 -
遍历每个数字组时,统计其中的奇偶数字数量:
- 新的偶数组合数 = 之前偶数组合数 × 当前偶数数量 + 之前奇数组合数 × 当前奇数数量。
- 新的奇数组合数 = 之前偶数组合数 × 当前奇数数量 + 之前奇数组合数 × 当前偶数数量。
-
更新后,继续处理下一个数字组。
-
-
边界处理:
当所有数字组遍历完成后,结果即为even_count的值,表示满足条件的方案总数。
实现效果
通过动态规划避免了对所有可能组合的暴力穷举,大大降低了复杂度。以 numbers = [123, 456, 789] 为例:
- 第一组奇偶分布为奇数 2、偶数 1,更新后偶数组合数为 1。
- 第二组奇偶分布为奇数 1、偶数 2,更新后偶数组合数为 6。
- 第三组奇偶分布为奇数 2、偶数 1,更新后偶数组合数为 14。
最终输出结果为14。
总结
本题通过奇偶性质的分析,将问题抽象为动态规划的状态转移,避免了组合的暴力穷举。核心难点在于公式推导以及状态的正确更新。这种方法不仅提升了效率,还增强了对数学与编程结合问题的解决能力,适合处理类似组合与选择类的题目。