LeetCode-下一个更大的数值平衡数

551 阅读2分钟

算法记录

LeetCode 题目:

  如果整数 x 满足:对于每个数位 d ,这个数位恰好在 x 中出现 d 次。那么整数 x 就是一个数值平衡数。

  给你一个整数 n ,请你返回 严格大于 n 的 最小数值平衡数 。


说明

一、题目

输入: n = 1
输出: 22
解释:
    22 是一个数值平衡数,因为:
    - 数字 2 出现 2 次 
    这也是严格大于 1 的最小数值平衡数。

二、分析

  • 题目剪短但是并不精悍,我们来分析一下什么叫做数值平衡数,从题意中解释的话理解为对一个十进制的数做每个进制位上的数据进行统计,如果统计里面出现了 9 这个数字,那么这个数就要求在整个数字统计中出现 9 次,以此类推其余情况。
  • 而且题目要求的返回比当前输入数要大的最小平衡数,也就限定了我们输出和考虑的范围。
  • 如果说当前的输入有 n 位,那么我们要求解的数字位数也就是 n 或者 n + 1,因为如果只用当前的位数可能拿不到比当前数更大的结果,但是使用位数加一之后是一定可以找到更优的解的。
  • 明确了方法之后我们来设计算法实现:
    • 首先求出当前输入数的位数;
    • 按照平衡数的规则生成对应的数列排序,也就是满足整个位数或者 +1 位数的平衡术生成条件;
    • 将生成条件进行全排列重新组成一个数字选择待处理;
    • 最后将所有的待选的数字和输入数字进行对比,选出大于且最小的最优答案。
class Solution {
    public int nextBeautifulNumber(int n) {
        int m = getNumber(n);
        List<Integer> ret = new ArrayList();
        result(m, ret);
        result(m + 1, ret);
        int min = Integer.MAX_VALUE;
        for(int r : ret) {
            if(r > n) min = Math.min(min, r);
        }
        return min;
    }
    public int getNumber(int n) {
        int number = 0;
        while(n != 0) {
            number++;
            n /= 10;
        }
        return number;
    }
    public void result(int n, List<Integer> ret) {
        List<Integer> temp = new ArrayList();
        dfs(n, 1, temp, ret, n);
    }
    public void dfs(int max, int min, List<Integer> temp, List<Integer> ret, int n) {
        if(max == 0) {
            int[] t = new int[n], flag = new int[n], tem = new int[n];
            int ind = 0;
            for(int i : temp) for(int j = 0; j < i; j++) {
                t[ind++] = i;
            }
            fullArray(t, ret, flag, 0, tem);
            return;
        } 
        for(int i = min; i <= max; i++) {
            if(max - i > i || i == max) {
                temp.add(i);
                dfs(max - i, i + 1, temp, ret, n);
                temp.remove(temp.size() - 1);
            }
        }
    }
    public void fullArray(int[] t, List<Integer> ret, int[] flag, int n, int[] temp) {
        if(n >= t.length) {
            int re = 0;
            for(int i : temp) {
                re = re * 10 + i;
            }
            ret.add(re); 
            return;
        }
        for(int i = 0; i < t.length; i++) {
            if(flag[i] == 1) continue;
            temp[n] = t[i];
            flag[i] = 1;
            fullArray(t, ret, flag, n + 1, temp);
            flag[i] = 0;
        }
    }
}

总结

考虑到了使用递归将排列进行选取,同时使用递归实现全排列的选取。