字典序排数相关算法

记录两道与数字的字典序排数相关的题目(字节常考)
在这里插入图片描述
在这里插入图片描述
把数字的字典序画出来看看马上就明白了。

class Solution {
    public List<Integer> lexicalOrder(int n) {
        List<Integer> ans = new ArrayList<>();
        int cur = 1;
        for(int i = 0; i < n; i++) {
            ans.add(cur);
            if(cur * 10 <= n)
                cur *= 10;
            else {
                // 枚举到当前前缀的最深处了,需要回到上一层并到下一个同层节点
                while(cur % 10 == 9 || cur >= n)
                    cur /= 10;
                cur++;
            }
        }
        return ans;
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

说人话核心思想就是用getSteps()求以一个数为根结点的字数总共包括多少个节点stpes;如果steps<=k;则说明我们要找的数不在这个子树里,直接用k减去steps,然后往右边走,cur++即可;
若steps>k,则说明我们要找到数在这个子树里,则cur * =10,k --;进入下一层搜索;
重复上述搜索直到k为0 为止。

可能你会想可以和上面那道一样一个个从小到大去遍历字典序直至第k个,但看一下k的取值范围就会发现很容易超时,所以只能通过求steps加快搜索;

class Solution {
    public int findKthNumber(int n, int k) {
        int cur=1;
        k--;
        while(k>0){
            int step=getSteps(cur,n);
            if(step<=k){
                k-=step;
                cur++;
            }
            else{
                cur*=10;
                k--;
            }
        }
        return cur;

    }
    //注意要下面的long型,否则会越界
    public int getSteps(int cur,long n){
        int step=0;
        long first=cur,last=cur;
        while(first<=n){
            step+=last-first+1;
            first=first*10;
            last= Math.min(last*10+9,n);
        }
        return step;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值