说在前面
🎈每天进行一道算法题目练习,今天的题目是“个位数字为 K 的整数之和”。
问题描述
给你两个整数 num
和 k
,考虑具有以下属性的正整数多重集:
- 每个整数个位数字都是
k
。 - 所有整数之和是
num
。
返回该多重集的最小大小,如果不存在这样的多重集,返回 -1
。
注意:
- 多重集与集合类似,但多重集可以包含多个同一整数,空多重集的和为
0
。 - 个位数字 是数字最右边的数位。
示例 1:
输入: num = 58, k = 9
输出: 2
解释:
多重集 [9,49] 满足题目条件,和为 58 且每个整数的个位数字是 9 。
另一个满足条件的多重集是 [19,39] 。
可以证明 2 是满足题目条件的多重集的最小长度。
示例 2:
输入: num = 37, k = 2
输出: -1
解释: 个位数字为 2 的整数无法相加得到 37 。
示例 3:
输入: num = 0, k = 7
输出: 0
解释: 空多重集的和为 0 。
提示:
0 <= num <= 3000
0 <= k <= 9
思路分析
首先我们应该要先理解一下题意,题目给出两个参数,分别是:
k
:我们可以使用的数 -> [0,3000]中个位数为k的数num
:我们需要使用[0,3000]中个位数为k的数组成的和
提取提示给出的信息:
- 还有要注意的一点是:
数字可以重复使用
- 再看一下num的取值范围:
0 <= num <= 3000
数据范围是0 <= num <= 3000
,所以我们可以使用动态规划,求出0-3000中每一个数字可以组成的最少个数:\
我们可以总结出公式,dp[num] = dp[i] + dp[num - i]
---> dp[i] = dp[j] + dp[i - j]
,可以推出所有可能组成的数值需要使用数字的个数,具体步骤如下:
- 1、统计个位数为k及其倍数的次数
let i = k;
let dp = new Array(num + 5).fill(0);
while(i <= num){
if(i == 0) i += 10;
if(i == num) return 1;
for(let j = 1; j * i <= num; j++){
dp[j * i] = j;
}
i += 10;
}
- 2、求组成所求的值得最小个数
if(dp[num]) res = dp[num];
for(let i = 0; i <= num; i++){
if(dp[i] && dp[num - i]) res = Math.min(dp[i] + dp[num - i],res);
}
AC代码
/**
* @param {number} num
* @param {number} k
* @return {number}
*/
var minimumNumbers = function(num, k) {
if(num == 0) return 0;
let i = k;
let res = Infinity;
let dp = new Array(num + 5).fill(0);
dp[0] = 0;
while(i <= num){
if(i == 0) i += 10;
if(i == num) return 1;
for(let j = 1; j * i <= num; j++){
dp[j * i] = j;
}
i += 10;
}
if(dp[num]) res = dp[num];
for(let i = 0; i <= num; i++){
if(dp[i] && dp[num - i]) res = Math.min(dp[i] + dp[num - i],res);
}
return res == Infinity ? -1 : res;
};
说在后面
🎉这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。