美文网首页
【教3妹学编程-算法题】统计强大整数的数目

【教3妹学编程-算法题】统计强大整数的数目

作者: 程序员小2 | 来源:发表于2024-02-13 17:49 被阅读0次
    瑟瑟发抖

    2哥 : 3妹,今年过年收到压岁钱了没呢。
    3妹:切,我都多大了啊,肯定没收了啊
    2哥 : 俺也一样,不仅没收到,小侄子小外甥都得给,还倒贴好几千
    3妹:哈哈哈哈,2叔叔,也给我这个小侄女点压岁钱啊
    2哥 :切,没啦没啦
    3妹:话说你最大是多少岁开始没人给压岁钱了啊?
    2哥:emmm, 大概是16岁,上高中开始的吧
    3妹:那2哥,你收到的最大红包是多少呢
    2哥:5千,是我奶奶给我的。
    2哥:好吧,回家不仅只有压岁钱,也要刷题啊,今天有一道“最大”的题目, 让我们先做一下吧~

    吃瓜

    题目:

    给你三个整数 start ,finish 和 limit 。同时给你一个下标从 0 开始的字符串 s ,表示一个 正 整数。

    如果一个 正 整数 x 末尾部分是 s (换句话说,s 是 x 的 后缀),且 x 中的每个数位至多是 limit ,那么我们称 x 是 强大的 。

    请你返回区间 [start..finish] 内强大整数的 总数目 。

    如果一个字符串 x 是 y 中某个下标开始(包括 0 ),到下标为 y.length - 1 结束的子字符串,那么我们称 x 是 y 的一个后缀。比方说,25 是 5125 的一个后缀,但不是 512 的后缀。

    示例 1:

    输入:start = 1, finish = 6000, limit = 4, s = "124"
    输出:5
    解释:区间 [1..6000] 内的强大数字为 124 ,1124 ,2124 ,3124 和 4124 。这些整数的各个数位都 <= 4 且 "124" 是它们的后缀。注意 5124 不是强大整数,因为第一个数位 5 大于 4 。
    这个区间内总共只有这 5 个强大整数。
    示例 2:

    输入:start = 15, finish = 215, limit = 6, s = "10"
    输出:2
    解释:区间 [15..215] 内的强大整数为 110 和 210 。这些整数的各个数位都 <= 6 且 "10" 是它们的后缀。
    这个区间总共只有这 2 个强大整数。
    示例 3:

    输入:start = 1000, finish = 2000, limit = 4, s = "3000"
    输出:0
    解释:区间 [1000..2000] 内的整数都小于 3000 ,所以 "3000" 不可能是这个区间内任何整数的后缀。

    提示:

    1 <= start <= finish <= 10^15
    1 <= limit <= 9
    1 <= s.length <= floor(log10(finish)) + 1
    s 数位中每个数字都小于等于 limit 。
    s 不包含任何前导 0 。

    思路:

    思考

    设 nums\textit{nums}nums 的异或和为 sss。

    定义 dfs(i,limitLow,limitHigh)表示构造第 i位及其之后数位的合法方案数,其余参数的含义为:

    limitHigh表示当前是否受到了 finish的约束(我们要构造的数字不能超过 finish。若为真,则第 iii 位填入的数字至多为 finish[i],否则至多为 9,这个数记作 hi。如果在受到约束的情况下填了 finish[i],那么后续填入的数字仍会受到 finish 的约束。例如 finish=123,那么 i=0填的是 1 的话,i=1的这一位至多填 2。
    limitLow 表示当前是否受到了 start的约束(我们要构造的数字不能低于 start。若为真,则第 i位填入的数字至少为 start[i],否则至少为 0,这个数记作 lo。如果在受到约束的情况下填了 start[i],那么后续填入的数字仍会受到 start 的约束。

    java代码:

    class Solution {
        public long numberOfPowerfulInt(long start, long finish, int limit, String s) {
            String low = Long.toString(start);
            String high = Long.toString(finish);
            int n = high.length();
            low = "0".repeat(n - low.length()) + low; // 补前导零,和 high 对齐
            long[] memo = new long[n];
            Arrays.fill(memo, -1);
            return dfs(0, true, true, low.toCharArray(), high.toCharArray(), limit, s.toCharArray(), memo);
        }
    
        private long dfs(int i, boolean limitLow, boolean limitHigh, char[] low, char[] high, int limit, char[] s, long[] memo) {
            if (i == high.length) {
                return 1;
            }
    
            if (!limitLow && !limitHigh && memo[i] != -1) {
                return memo[i]; // 之前计算过
            }
    
            // 第 i 个数位可以从 lo 枚举到 hi
            // 如果对数位还有其它约束,应当只在下面的 for 循环做限制,不应修改 lo 或 hi
            int lo = limitLow ? low[i] - '0' : 0;
            int hi = limitHigh ? high[i] - '0' : 9;
    
            long res = 0;
            if (i < high.length - s.length) { // 枚举这个数位填什么
                for (int d = lo; d <= Math.min(hi, limit); d++) {
                    res += dfs(i + 1, limitLow && d == lo, limitHigh && d == hi, low, high, limit, s, memo);
                }
            } else { // 这个数位只能填 s[i-diff]
                int x = s[i - (high.length - s.length)] - '0';
                if (lo <= x && x <= Math.min(hi, limit)) {
                    res = dfs(i + 1, limitLow && x == lo, limitHigh && x == hi, low, high, limit, s, memo);
                }
            }
    
            if (!limitLow && !limitHigh) {
                memo[i] = res; // 记忆化 (i,false,false)
            }
            return res;
        }
    }
    

    相关文章

      网友评论

          本文标题:【教3妹学编程-算法题】统计强大整数的数目

          本文链接:https://www.haomeiwen.com/subject/egxsadtx.html