Medium
题目描述
一个整数 x 是数值平衡的,当且仅当对于数字 x 中的每个数字 d,数字 d 在 x 中恰好出现 d 次。
给定一个整数 n,返回严格大于 n 的最小数值平衡数。
示例 1:
输入:n = 1
输出:22
解释:
22 是数值平衡的,因为:
- 数字 2 出现了 2 次。
它也是严格大于 1 的最小数值平衡数。
示例 2:
输入:n = 1000
输出:1333
解释:
1333 是数值平衡的,因为:
- 数字 1 出现了 1 次。
- 数字 3 出现了 3 次。
它也是严格大于 1000 的最小数值平衡数。
注意 1022 不能作为答案,因为 0 出现的次数超过了 0 次。
示例 3:
输入:n = 3000
输出:3133
解释:
3133 是数值平衡的,因为:
- 数字 1 出现了 1 次。
- 数字 3 出现了 3 次。
它也是严格大于 3000 的最小数值平衡数。
约束条件:
- 0 ≤ n ≤ 10^6
提示:
- 下一个数值平衡数距离 n 能有多远?
- 在给定约束下,最大的数值平衡数是什么?
解题思路
解题思路
这道题要求找到严格大于给定数字 n 的最小数值平衡数。数值平衡数的定义是:对于数字中的每个数字 d,它在整个数字中恰好出现 d 次。
方法一:枚举法(推荐)
由于约束条件 n ≤ 10^6,我们可以直接从 n+1 开始枚举每个数字,检查它是否为数值平衡数。这种方法简单直接,且由于数值平衡数相对稀少,不会超时。
检查数值平衡数的步骤:
- 统计数字中每个数位的出现次数
- 检查每个出现的数位 d 是否恰好出现 d 次
- 特别注意数字 0:如果 0 出现,那么它必须出现 0 次(矛盾),所以包含 0 的数字不可能是数值平衡数
方法二:预计算
我们可以预先生成所有可能的数值平衡数,然后使用二分查找。但考虑到约束范围不大,方法一已经足够高效。
通过分析可知,在给定范围内,最大的数值平衡数是 1333333(7位数),所以枚举的范围是有限的。
代码实现
class Solution {
public:
int nextBeautifulNumber(int n) {
for (int num = n + 1; ; num++) {
if (isBeautiful(num)) {
return num;
}
}
}
private:
bool isBeautiful(int num) {
vector<int> count(10, 0);
int temp = num;
// 统计每个数位的出现次数
while (temp > 0) {
count[temp % 10]++;
temp /= 10;
}
// 检查是否为数值平衡数
for (int i = 0; i < 10; i++) {
if (count[i] != 0 && count[i] != i) {
return false;
}
}
return true;
}
};
class Solution:
def nextBeautifulNumber(self, n: int) -> int:
def is_beautiful(num):
count = [0] * 10
temp = num
# 统计每个数位的出现次数
while temp > 0:
count[temp % 10] += 1
temp //= 10
# 检查是否为数值平衡数
for i in range(10):
if count[i] != 0 and count[i] != i:
return False
return True
num = n + 1
while True:
if is_beautiful(num):
return num
num += 1
public class Solution {
public int NextBeautifulNumber(int n) {
for (int num = n + 1; ; num++) {
if (IsBeautiful(num)) {
return num;
}
}
}
private bool IsBeautiful(int num) {
int[] count = new int[10];
int temp = num;
// 统计每个数位的出现次数
while (temp > 0) {
count[temp % 10]++;
temp /= 10;
}
// 检查是否为数值平衡数
for (int i = 0; i < 10; i++) {
if (count[i] != 0 && count[i] != i) {
return false;
}
}
return true;
}
}
var nextBeautifulNumber = function(n) {
function isBeautiful(num) {
const count = new Array(10).fill(0);
let temp = num;
// 统计每个数位的出现次数
while (temp > 0) {
count[temp % 10]++;
temp = Math.floor(temp / 10);
}
// 检查是否为数值平衡数
for (let i = 0; i < 10; i++) {
if (count[i] !== 0 && count[i] !== i) {
return false;
}
}
return true;
}
for (let num = n + 1; ; num++) {
if (isBeautiful(num)) {
return num;
}
}
};
复杂度分析
| 复杂度 | 分析 |
|---|---|
| 时间复杂度 | O(k × log k),其中 k 是下一个数值平衡数与 n 的差值,log k 是检查每个数字的位数 |
| 空间复杂度 | O(1),只使用固定大小的数组存储数位计数 |