• 306周赛t4 6151. 统计特殊整数 记忆化搜索


    6151. 统计特殊整数

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

    给你一个  整数 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 * 1e9

    来源:力扣(LeetCode
    链接:https://leetcode.cn/problems/count-special-integers
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    做题结果

    成功,但是比赛t4第一解2000多ms,如果rejudge取第二次解就很慢T T。而且第二解也没有缓存,几百毫秒,不知道会不会有例子会卡。其实我知道有答案可以抄,之前刚好写过,但是写过不熟,就顺便练练【其实很有底气的话,反而会抄,因为符合规则,而且自身有把握,自己是会的】。原题来自:1012. 至少有 1 位重复的数字,用总数减掉这个答案就可以了,基本完全一样

    方法:数学+DFS

    先排序组合算少一位的,再算刚刚好的

    1. class Solution {
    2. public int countSpecialNumbers(int n) {
    3. char[] cs = String.valueOf(n).toCharArray();
    4. int len = cs.length;
    5. int pre = 1;
    6. int sum = 0;
    7. int[] time = new int[]{9,9,8,7,6,5,4,3,2,1};
    8. for(int i = 0; i < len-1; i++){
    9. pre=pre*time[i];
    10. sum += pre;
    11. }
    12. return sum + dfs(cs,n,0,0,new boolean[10],true);
    13. }
    14. private int dfs(char[] cs, int num, int v,int index, boolean[] visited,boolean limit){
    15. if(index == cs.length) return 1;
    16. int ans = 0;
    17. int max = limit?cs[index]-'0':9;
    18. for(int i = 0; i <= max; i++){
    19. if(i==0&&index==0) continue;
    20. if((long)v*10+i>num) continue;
    21. if(visited[i]) continue;
    22. visited[i] = true;
    23. ans += dfs(cs,num,v*10+i,index+1,visited,limit && i==max);
    24. visited[i] = false;
    25. }
    26. return ans;
    27. }
    28. }

    方法:记忆化搜索(这里取的是自己1012改,那个写的好一点)

    1. 把所有因素,是否有前导0,是否访问过,当前值,索引,是否前面取的数字踩线这些因素,合成 key, 记忆答案

    2. 逐个取值即可,注意到达末尾时可取一个

    3. 哈希去重:因为不能出现重复需要提前记忆

    4. 最后一个0:最后会多算一个0,需要减掉

    5. 限定:如果前面刚好取到最大值,则后续值不能超过当前数字限定值

    6. 前导0:前导0不必考虑数字去重

    1. class Solution {
    2. public int countSpecialNumbers(int n) {
    3. Deque deque = new LinkedList<>();
    4. int v = n;
    5. while (v>0){
    6. deque.offerFirst(v%10);
    7. v = v/10;
    8. }
    9. return dfs(new ArrayList<>(deque),0, 0,0,true,true)-1;
    10. }
    11. Map cnts = new HashMap<>();
    12. private int dfs(List n, int visited,int curr,int index,boolean limit,boolean isLeadingZero){
    13. if(index==n.size()){
    14. return 1;
    15. }
    16. int key = ((visited*4+(limit?2:0)+(isLeadingZero?1:0))<<4)+index;
    17. if(cnts.containsKey(key)) {
    18. return cnts.get(key);
    19. }
    20. int ans = 0;
    21. int max = limit?n.get(index):9;
    22. for(int i = 0; i <= max; i++){
    23. if(((visited>>i)&1)==0){
    24. if(!isLeadingZero || i!=0) visited = (visited|(1<
    25. ans += dfs(n,visited,curr*10+i,index+1,limit&&i==max,isLeadingZero&&i==0);
    26. if(!isLeadingZero || i!=0) visited = (visited^(1<
    27. }
    28. }
    29. cnts.put(key,ans);
    30. return ans;
    31. }
    32. }

  • 相关阅读:
    离线数据处理——子任务一:数据抽取
    机器学习-计算数据之间的距离
    爬虫Python
    gcc和Makefile,多文件编译器
    为什么mysql索引用B+树而不用Hash表
    工厂模式——工厂方法模式+注册表
    年轻人不用太过于努力
    Spring注解家族介绍:@RestController
    C++----类型转换
    台式电脑怎么格式化重装系统
  • 原文地址:https://blog.csdn.net/yu_duan_hun/article/details/126337082