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

67 阅读3分钟

数字组合与偶数和问题解析

问题背景

本题是一道颇具挑战性的组合优化问题,要求从给定的多个数字组中,选择一个数字组合成新的数字,并满足特定的数学条件:新数字的各位数字之和必须为偶数。这个问题不仅考验编程技巧,还需要深入理解递归和组合算法的精髓。

问题分析

题目的核心挑战在于:

  1. 从多个数字组中,每组选择一个数字
  2. 组合这些数字成为一个完整的数字
  3. 计算这个数字各位数字之和
  4. 判断是否为偶数
  5. 统计并去重符合条件的数字数量

与传统的组合问题相比,本题增加了数字和的约束条件,使得问题更加复杂。

算法设计

经过深入分析,我们选择使用深度优先搜索(DFS)递归方法来解决这个问题。算法的核心思路如下:

  1. 预处理输入数据:将整数转换为字符串,便于后续遍历

  2. 设计递归函数,实现以下功能:

    • 遍历每个数字组
    • 从每个数字组选择一个数字
    • 逐步构建完整数字
  3. 在递归的终止条件(遍历完所有数字组)时:

    • 计算当前数字的各位数字和
    • 判断是否为偶数
    • 将符合条件的数字加入结果集
  4. 使用set去重,确保结果的唯一性

#include <iostream>
#include <set>
#include <string>
#include <vector>

std::set<int> valid_numbers;

void dfs(const std::vector<std::string> &str_numbers, size_t index,
         std::string current) {
  // 如果已处理所有数字组
  if (index == str_numbers.size()) {
    // 转换为整数并计算数字和
    if (!current.empty()) {
      int num = std::stoi(current);
      int digit_sum = 0;
      for (char c : current) {
        digit_sum += c - '0';
      }
      // 偶数和则加入结果集
      if (digit_sum % 2 == 0) {
        valid_numbers.insert(num);
      }
    }
    return;
  }

  // 遍历当前数字组的每一位
  for (char c : str_numbers[index]) {
    dfs(str_numbers, index + 1, current + c);
  }
}

int solution(std::vector<int> numbers) {
  // 转换输入数字为字符串数组
  std::vector<std::string> str_numbers;
  for (int num : numbers) {
    str_numbers.push_back(std::to_string(num));
  }

  // 清空上一次的结果集
  valid_numbers.clear();

  // 开始递归
  dfs(str_numbers, 0, "");

  // 返回结果数量
  return valid_numbers.size();
}

代码实现关键点

  • 采用类封装递归方法,提高代码的结构性
  • 递归函数dfs负责深度优先搜索和数字组合
  • 通过字符串拼接构建新数字,避免复杂的数学运算
  • 使用set自动去重,简化处理逻辑

复杂度分析

时间复杂度

  • O(m^n),其中m是每个数字组的平均长度,n是数字组的数量
  • 每个数字组都需要遍历,形成指数级复杂度

空间复杂度

  • O(m^n),用于存储所有符合条件的数字组合
  • 递归调用栈和结果集都会占用空间

算法优势

  1. 代码简洁明了
  2. 处理灵活,适用于不同长度和数量的数字组
  3. 通过递归实现复杂的组合逻辑
  4. 使用标准库工具简化实现

潜在改进方向

  • 对于大规模输入,可以考虑剪枝优化
  • 可以预估可能的最大组合数,提前设置上限
  • 使用更高效的去重策略

编程技巧

  • 字符串转换很关键,std::to_string()std::stoi()是常用工具
  • 字符与整数转换技巧:c - '0'
  • 递归函数设计要点:明确终止条件和递归逻辑

测试用例思考

题目给出三个测试用例,体现了问题的复杂性:

  1. [123, 456, 789] - 多组数字,需要全面组合
  2. [123456789] - 单一长数字,考验算法的适应性
  3. [14329, 7568] - 不同长度数字组,验证算法的通用性