力扣(leetcode)每日一题 2376 统计特殊整数 | 数位dp | 暴力递归+记忆化搜索

题干

2376. 统计特殊整数

如果一个正整数每一个数位都是 互不相同 的,我们称它是 特殊整数

给你一个 整数 n ,请你返回区间 [1, n] 之间特殊整数的数目。

示例 1:

**输入:**n = 20

**输出:**19

**解释:**1 到 20 之间所有整数除了 11 以外都是特殊整数。所以总共有 19 个特殊整数。

示例 2:

**输入:**n = 5

**输出:**5

**解释:**1 到 5 所有整数都是特殊整数。

示例 3:

**输入:**n = 135

**输出:**110

**解释:**从 1 到 135 总共有 110 个整数是特殊整数。

不特殊的部分数字为:22 ,114 和 131 。

提示:

  • 1 <= n <= 2 * 109
题解 1 时间上过不了
java 复制代码
  
    public static int countSpecialNumbers(int n) {  
        int count = 0;  
        for (int i = 1; i <= n; i++) {  
            HashSet<Integer> set = new HashSet<>();  
            int tmp = i;  
            int c = 0;  
            while (tmp > 0) {  
                int i1 = tmp % 10;  
                set.add(i1);  
                c++;  
                tmp /= 10;  
            }  
            if (c != set.size()) {  
                count++;  
            }  
        }  
        return n - count;  
    }
    
题解 2

动态规划,有想过,但是实现失败了

还有考虑过数学技巧的,用公式硬凑,这个是死路

java 复制代码
public static int countSpecialNumbers(int n) {  
    int[][] dp = new int[String.valueOf(n).length()][1 << 10];    // 这里初始化dp赋值-1  n的长度和2的10次方 记录数字1,2,3,4,5,6,7,8,9 是否有被使用过  
    for (int[] ints : dp) {  
        Arrays.fill(ints, -1);  
    }  
    return f(0, true, 0, false, String.valueOf(n), dp) - 1;  
}  
  
public static int f(int index,        // 递归的位置  
                    boolean isLimit,  // 最后有最高位的限制  
                    int mask,         // 记录已经使用过的数字  
                    boolean isNum,    // 是否开始组成数字  
                    String n,         // 数字n  
                    int[][] dp) {     // 记忆化搜索  
    if (index == n.length()) {  
        return 1;  
    }  
    if (dp[index][mask] != -1 && isNum & !isLimit) {  
        return dp[index][mask];  
    }  
    int res = 0;  
    if (!isNum) {  
        res += f(index + 1, false, mask, false, n, dp);  
    }  
    // 看是否受限制  
    int top = isLimit ? n.charAt(index) - '0' : 9; // 如果有限制,就取最高位,如果没有限制就取9  
    for (int i = isNum ? 0 : 1; i <= top; i++) {  
        // 当位数可以使用  
        if ((mask & (1 << i)) == 0) {  
            // 递归  
            res += f(index + 1,  
                    isLimit && i == top,  // 如果本身有限制,这次又是取最高位,那么还是需要限制最高位  
                    mask | (1 << i),             // 1进行左移i位 然后求与   比如00011 | 1<< 3 就是   00111                    true,                 // 如果isNum为false,那么i开始位是1    如果isNum为true  
                    n,  
                    dp);  
        }  
    }  
    if (isNum & !isLimit) {  
        dp[index][mask] = res;            // 只有是数字,并且没有限制的时候才进行记忆化  
    }  
    return res;  
}
总结

这个不好分析呀。想到了第一次做也憋不出暴力递归

不清楚这个是不是数位dp,但是肯定可以归到暴力递归+记忆化搜索

他需要两个参数来isNum,isLimit来分析,还要掌握位运算的技巧来判断数字是否使用过

相关推荐
sin_hielo15 小时前
leetcode 756(枚举可填字母)
算法·leetcode
Jeremy爱编码15 小时前
leetcode热题子集
算法·leetcode·职场和发展
csg110715 小时前
LORA网络的“最后一公里”难题:当信号被重重阻挡,我们有哪些“方法”来增强覆盖?
单片机·嵌入式硬件·物联网·算法
brave and determined15 小时前
传感器学习(day18):智能手机3D结构光:解锁未来的第三只眼
嵌入式硬件·算法·3d·智能手机·tof·嵌入式设计·3d结构光
CoovallyAIHub15 小时前
当小龙虾算法遇上YOLO:如何提升太阳能电池缺陷检测精度?
深度学习·算法·计算机视觉
Tisfy16 小时前
LeetCode 756.金字塔转换矩阵:深度优先搜索
leetcode·矩阵·深度优先
努力学算法的蒟蒻16 小时前
day48(12.29)——leetcode面试经典150
算法·leetcode·面试
CoovallyAIHub16 小时前
AI如何精准关联照片与抽象平面图?C3数据集迈向3D视觉多模态
深度学习·算法·计算机视觉
GEO AI搜索优化助手16 小时前
数据共振:GEO与SEO的算法协同与智能决策系统
人工智能·算法·搜索引擎·生成式引擎优化·ai优化·geo搜索优化
java修仙传16 小时前
力扣hot100:有效的括号
算法·leetcode·职场和发展