青训营刷题 二分数字组合 简单题

24 阅读2分钟

问题描述

小F面临一个有趣的挑战:给定一个数组,她需要将数组中的数字分为两组。分组的目标是使得一组数字的和的个位数等于给定的 A,另一组数字的和的个位数等于给定的 B。除此之外,还有一种特殊情况允许其中一组为空,但剩余数字和的个位数必须等于 A 或 B。小F需要计算所有可能的划分方式。

例如,对于数组 [1, 1, 1] 和目标 A = 1,B = 2,可行的划分包括三种:每个 1 单独作为一组,其余两个 1 形成另一组。如果 A = 3,B = 5,当所有数字加和的个位数为 3 或 5 时,可以有一组为非空,另一组为空。

测试样例

样例1:

输入:n = 3,A = 1,B = 2,array_a = [1, 1, 1]
输出:3

样例2:

输入:n = 3,A = 3,B = 5,array_a = [1, 1, 1]
输出:1

样例3:

输入:n = 2,A = 1,B = 1,array_a = [1, 1]
输出:2

样例4:

输入:n = 5,A = 3,B = 7,array_a = [2, 3, 5, 7, 9]
输出:0

思路

1、如果全部数字相加的个位数等于A或B,那么返回1;

2、如果相加的个位数不等于(A+B)%10,那么返回0;

3、一部分数相加的个位数等于A,另一部分(必然)等于B。

使用动态规划,f[i][j]表示从数组中任意选i个数,它们的和的个位数是j的分组的个数。

完整代码

def solution(n, A, B, array_a):
    array_a = [x % 10 for x in array_a]
    total_sum = sum(array_a)
    total_sum %= 10

    if total_sum == A or total_sum == B:
        return 1
    if total_sum != (A + B) % 10:
        return 0
    
    f = [[0 for _ in range(10)] for _ in range(n + 1)]
    f[0][0] = 1
    for i in range(1, n + 1):
        for j in range(10):
            f[i][j] += f[i - 1][j]
            f[i][j] += f[i - 1][(j - array_a[i - 1] + 10) % 10]
    return f[n][A] // f[n][B]也行

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution(3, 1, 2, [1,1,1]) == 3 )
    print(solution(3, 3, 5, [1,1,1]) == 1 )
    print(solution(2, 1, 1, [1,1]) == 2 )

空间复杂度O(n)O(n),时间复杂度O(n)O(n)