问题描述
小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 )
空间复杂度,时间复杂度