目标
给你一个数字数组 digits,你需要从中选择三个数字组成一个三位偶数,你的任务是求出 不同 三位偶数的数量。
注意:每个数字在三位偶数中都只能使用 一次 ,并且 不能 有前导零。
示例 1:
输入: digits = [1,2,3,4]
输出: 12
解释: 可以形成的 12 个不同的三位偶数是 124,132,134,142,214,234,312,314,324,342,412 和 432。注意,不能形成 222,因为数字 2 只有一个。
示例 2:
输入: digits = [0,2,2]
输出: 2
解释: 可以形成的三位偶数是 202 和 220。注意,数字 2 可以使用两次,因为数组中有两个 2 。
示例 3:
输入: digits = [6,6,6]
输出: 1
解释: 只能形成 666。
示例 4:
输入: digits = [1,3,5]
输出: 0
解释: 无法形成三位偶数。
说明:
- 3 <= digits.length <= 10
- 0 <= digits[i] <= 9
思路
有一个数字数组 digits,数组元素为 0 ~ 9 ,从中选择 3 个组成一个三位偶数,求不同的三位偶数的个数。
从结果来考虑,三位数 100 ~ 999,针对每个数字判断能否由数组中的数字构成即可。
从构造的角度考虑,需要保证个位是偶数,且百位不是 0,要求数字不同,需要维护可用的数字种类,需要知道每个数字的已使用次数,可以使用回溯。
代码
/**
* @date 2026-09-11 8:56
*/
public class TotalNumbers3483 {
public int totalNumbers(int[] digits) {
int[] d = new int[10];
for (int num : digits) {
d[num]++;
}
int res = 0;
for (int num = 100; num < 999; num += 2) {
if (valid(num, d)) {
res++;
}
}
return res;
}
public boolean valid(int num, int[] d) {
int[] tmp = new int[10];
while (num > 0) {
tmp[num % 10]++;
num /= 10;
}
for (int i = 0; i < 10; i++) {
if (d[i] < tmp[i]) {
return false;
}
}
return true;
}
public int totalNumbers_v0(int[] digits) {
int[] d = new int[10];
for (int num : digits) {
d[num]++;
}
int res = 0;
// 枚举百位
for (int i = 1; i < d.length; i++) {
if (d[i] == 0) {
continue;
}
d[i]--;
res += dfs(0, i, d);
d[i]++;
}
return res;
}
int dfs(int index, int num, int[] d) {
if (index == 2) {
// 第三个数如果是偶数返回 1
return num % 2 == 0 ? 1 : 0;
}
int res = 0;
// 枚举十位
for (int i = 0; i < d.length; i++) {
if (d[i] == 0) {
continue;
}
d[i]--;
res += dfs(index + 1, i, d);
d[i]++;
}
return res;
}
}
性能
