原题:2310. 个位数字为 K 的整数之和 - 力扣(LeetCode)
解题的思路类似于:322. 零钱兑换 - 力扣(LeetCode)
考虑用动态规划来解,对于本题。当考虑M在个位等于k的情况下的最少集合数,可以通过枚举所有小于等于M且个位为k的数。分别为:k, 10 + k,20 + k, 30 + k,40 + k....
其次,我们可以先检查下能否用个位等于k来组合出M,具体的思路我这里比较笨拙,就是把1到10乘一遍然后计算个位看有没有出现。如下:
private boolean check(int num, int k) {
int right = num % 10;
for (int i = 1; i <= 10; i++) {
if ((i * k) % 10 == right && (i * k) <= num) {
return true;
}
}
return false;
}
完整代码:
public int minimumNumbers(int num, int k) {
if (num == 0) {
return 0;
}
if (num % 10 == k) {
return 1;
}
int[][] mem = new int[num + 1][10];
for (int i = 0; i < num + 1; i++) {
for (int j = 0; j < 10; j++) {
if (!check(i, j)) {
mem[i][j] = -1;
continue;
}
if (i % 10 == j) {
mem[i][j] = 1;
continue;
}
if (i < j) {
mem[i][j] = -1;
continue;
}
mem[i][j] = Integer.MAX_VALUE;
for (int l = j; l < i; l += 10) {
//System.out.println(i + " " + j + " " + l);
if (mem[i - l][j] != -1) {
mem[i][j] = Math.min(mem[i][j], 1 + mem[i - l][j]);
}
}
}
}
return mem[num][k];
}
// 这种写法num = 10,k = 8 的时候判断不出来
// private boolean check(int num, int k) {
// int right = num % 10;
// for (int i = 0; i < 10; i++) {
// if ((i * k) % 10 == right) {
// return true;
// }
// }
// return false;
// }
private boolean check(int num, int k) {
int right = num % 10;
for (int i = 1; i <= 10; i++) {
if ((i * k) % 10 == right && (i * k) <= num) {
return true;
}
}
return false;
}