数字分组求偶数和
问题描述
小M面对一组从 1 到 9 的数字,这些数字被分成多个小组,并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。
numbers: 一个由多个整数字符串组成的列表,每个字符串可以视为一个数字组。小M需要从每个数字组中选择一个数字。
例如对于[123, 456, 789],14个符合条件的数为:147 149 158 167 169 248 257 259 268 347 349 358 367 369。
解题思路
该问题可以看作是一个多组数字的选择问题,要求从每个数字组中选择一个数字,组成的数字的各位和为偶数。由于对时间复杂度要求不高,我们可以采用暴搜,具体的思路如下:
- 初始化数字组:每个数字组由多个数字组成。可以通过遍历每个数字组,选择其中一个数字,累加到当前的数字和中。
- 目标条件:累加的数字和必须为偶数。最终,我们需要计算出符合这一条件的所有组合方式。
- 使用深度优先搜索(DFS):遍历每个数字组的所有数字,通过递归的方式进行选择。每次选择一个数字后,检查其对当前和的影响,并继续递归。
- 递归的终止条件:当遍历完所有的数字组时,检查当前的数字和是否为偶数,若是,则计数加1。
代码实现
package main
import "fmt"
func solution(numbers []int) int {
// 将数字转为字符串
sub := make([]string, len(numbers))
for i, num := range numbers {
sub[i] = fmt.Sprintf("%d", num)
}
return dfs(sub, 0, 0)
}
// 暴搜,参数分别为:当前字符串数组、当前处理的数组号和当前数字和
func dfs(numbers []string, index int, currentSum int) int {
// 如果已经搜完,判断当前数字和是否为偶数
if index == len(numbers) {
if currentSum%2 == 0 {
return 1
}
return 0
}
cnt := 0
// 遍历当前组每个数字
for i := 0; i < len(numbers[index]); i++ {
num := int(numbers[index][i] - '0') // 将字符转换为数字
// 递归调用,选择下一个组的数字,并累加当前数字和
cnt += dfs(numbers, index+1, currentSum+num)
}
return cnt
}
func main() {
fmt.Println(solution([]int{123, 456, 789}) == 14)
fmt.Println(solution([]int{123456789}) == 4)
fmt.Println(solution([]int{14329, 7568}) == 10)
}
代码解析
- 函数
solution:接收一个数字组列表numbers,将其转化为字符串列表sub。然后调用dfs函数开始暴搜,寻找符合条件的组合,并返回符合条件的情况总数。 - 深度优先搜索(DFS):
dfs函数递归遍历每个数字组的所有数字,尝试将每个数字加入到当前的和currentSum中。每次递归到一个数字组时,选择一个数字后递归进入下一个数字组。 - 递归终止条件:当
index == len(numbers)时,表示已经遍历完所有的数字组,检查当前的和currentSum是否为偶数,如果是偶数,则符合条件,计数cnt加1。
知识点总结
-
深度优先搜索(DFS):DFS 是一种用于遍历树状结构或图形结构的算法,尤其适用于递归问题。在此问题中,DFS 用来遍历每个数字组的数字组合,通过递归深度地选取数字,直到构建出完整的数字序列,并检查其和是否满足条件。
-
回溯思想:该问题的求解过程中,采用了回溯的方式进行遍历。每次递归选择一个数字后,继续向下探索,最终得到所有可能的组合方式,并通过判断每个组合的和是否为偶数来进行筛选。
-
字符到数字的转换:在处理每个数字组时,我们使用
numbers[index][i] - '0'将字符型数字转换为整型数字。这个技巧在处理字符串中的数字时很常用。 -
递归的终止条件:递归在遍历完整个数字组后终止,终止时需要检查当前和是否为偶数。如果是偶数,则返回 1,表示这是一个符合条件的组合;如果不是偶数,则返回 0。最后作用到上一层的cnt中,由最外层dfs返回最终结果。
-
空间优化与递归效率:递归过程中,通过传递当前的数字和
currentSum和索引index,避免了不必要的计算,并能够在每层递归时逐步更新和,直到所有可能的组合都被检查过,在问题规模相对较小的情况下,能有效求解。
实践记录和工具运用
在 MarsCode AI 刷题过程中,结合题目解析、图解辅助,能提升编程技能。除此之外,在使用过程中我还感受到以下优点:
1. 即时反馈和代码优化:MarsCode AI 可以即时评估提交的代码,并提供优化建议。除了AC,还能通过 AI 的提示来改进代码的时间复杂度、空间复杂度,或代码风格。对提升编程能力、代码质量有很大帮助。
2. 多样化的题型:题库中涵盖了大量的题型,包括动态规划、队列、位运算、栈、数学、贪心、双指针、图论、模拟等。通过多维度的练习,能够提升不同领域的综合能力,而不仅仅局限于某一个特定领域的知识。
3. 题库难度分级:题库分为简单、中等、困难,能逐渐提高代码水平过程中,保持挑战感。这种“由浅入深”的学习方式有助于在实践中不断突破自己。
总结
通过在 MarsCode AI 上解决数字分组求偶数和问题,我学到了如何通过深度优先搜索(DFS)来解决多组数字选择的问题,并深入掌握了字符串解析、数字转换以及回溯思想的应用。结合 AI 辅助和自我总结的过程,提高了我的编程能力,也进一步深化了对算法和数据结构的理解。