问题描述
小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
解题思路
- 要计算一个数字的各位之和是否为偶数,实际上只需要知道这个数字里有多少个奇数,如果奇数的个数为偶数个,数字和就为偶数
- 可以这样理解:如果我们目前已知有a个偶数组合,b个奇数组合,在统计下一个’大‘数字时我们发现,这个数字里有c个偶数和d个奇数
- 对于任意的偶数组合数,再增加任意一个偶数 组合数仍然为偶数
- 对于任意的奇数组合数,再增加任意一个奇数 组合数就可以变为偶数
- 那么 在增加了这一组数字之后偶数组合数的数量就变为a * c + b * d(偶数组合 * 偶数个数 + 奇数组合 * 奇数个数)
- 反之 奇数组合数就为a * d + b * c(偶数组合 * 奇数个数 + 奇数组合 * 偶数个数)
- 举个例子:我们已知有两个偶数组合 13 15 一个奇数组合 35 。发现下一组为1 3 4这三个数字,其中含有两个奇数和一个偶数。那么任意一个偶数组合增加任意一个偶数(也是该组唯一一个偶数)仍然是偶数,任意一个奇数组合增加任意一个奇数(1 3 都可以)即可变为偶数。偶数组合的数量从2变为2(偶数组合) * 1(偶数个数) + 1(奇数组合) * 2(奇数数量) = 4个(134 154 351 353)。
算法流程
1.初始化变量
1.evenNumber
该变量用来记录当前已经计算好的偶数组合数。 因为一个数也不选时,和为0为偶数,所以该变量应该初始化为1
2.oddNUmber
该变量用来记录当前已经计算好的奇数组合数
2.循环遍历每一个分组(数组中的每一个‘大’数字为一个分组)
1.循环遍历统计每一个分组中的奇数和偶数
这一步操作的目的是为了取出每一个分组中奇数和偶数的个数。我们分别选择用evenCount和oddCount两个变量来接收
1.遍历出数组中的每一个’大‘数字
2.遍历出每一个’大‘数字中的字符
这里我们选择使用strconv标准库中的Itoa函数将每一个大数字转换成一个字符串,再对字符串进行遍历,统计每一个分组中的奇数和偶数个数 注:这里不能直接使用int(digit)否则返回的是字符所对应的ASCII码,所以使用int(digit - '0')
3.动态规划维护变量
1.使用动态规划维护evenNumber和oddNumer
- newEvenNumber = evenNumber * evenCount + oddNumber * oddCount
- newOddNumber = evenNunber * oddCount + oddNumber + evenCount
2.对变量进行更新
更新evenNumber和oddNumber为newEvenNumber和NewOddNumber
代码展示
package main
import (
"fmt"
"strconv"
)
func solution(numbers []int) int {
// 初始化两个变量 一个当前的偶数组合数 一个记录当前的奇数组合数
evenNumber := 1 //用来记录当前的偶数组合数 一个数字也不选为0也为偶数 初始化为1
oddNumber := 0 //用来记录当前的奇数组合数
//循环遍历 统计每个分组(数组中的每一个数字为一个分组)中的奇数和偶数
for _, group := range numbers {
evenCount := 0 //统计偶数
oddCount := 0 //统计奇数
groupStr := strconv.Itoa(group)
for _, digit := range groupStr {
num := int(digit - '0') //修正数字转换 不然实际上返回的是ascii码
if num%2 == 0 {
evenCount++
} else {
oddCount++
}
}
//如果当前组合数为偶数 再加上一个偶数仍然为偶数
//如果当前组合数为奇数 再加上一个奇数即可变为偶数
//所以新的偶数组合数应该为
//当前偶数组合数 * 新增的偶数的个数 + 当前奇数组合数 * 新增的奇数的数量
newEvenNumber := evenNumber*evenCount + oddNumber*oddCount
//反之 新的奇数组合数应为
//当前偶数组合数 * 新增的奇数的个数 + 当前奇数组合数 * 新增的偶数的数量
newOddNum := evenNumber*oddCount + oddNumber*evenCount
//更新当前的组合数
evenNumber = newEvenNumber
oddNumber = newOddNum
}
//返回偶数组合数
return evenNumber
}
func main() {
// You can add more test cases here
fmt.Println(solution([]int{123, 456, 789}) == 14)
fmt.Println(solution([]int{123456789}) == 4)
fmt.Println(solution([]int{14329, 7568}) == 10)
}
```
```