[leetcode]440字典序的第K小数字,贪心

题意

n个正整数,按字典序排序,求第k个数字是多少?n的最大取值为10的9次方

思路

如果给定一个数字ans和范围n,求它在n中字典序排第几?你会发现。。。一点都不好求!
关键就是你还需要分别求出个位数、十位数、百位数等等不同位数中小于等于n的所有数字的字典序小于ans的个数再求和。所以这里我们题目要求的ans,我们就需要从前往后的决定每一个位要赋予什么值
这里有句废话,k = 1的时候,ans =1。但我们可以知道,第一个数字的第一个位一定是1,而在n不为1的时候,有多少个1开头的数字?又有多少个x开头的数字(x为1~9)?

假设我们的ans前3为已经确定321XXX,能不能算出n中有多少个值会比这个321XXX要小?那么就要算出1XXXXX开头,2XXXXX开头,30XXXX开头,31XXXX开头,32XXXX开头的个数.
带着这点看代码。这里的ans(未跑出循环时)是代表已确定前几位,中间位可变,后几位未定的状态,可以想象成 … XXX_??? …的状态,就是字典序的前几位是确定的,但循环的时候ans的最低位是可以变动的,然后后面的位置未定,可有数字也可为空

ol变量和ne变量作为确定目前ans的最低位是否定,看代码的第二层循环,是用来确定ans为前缀的情况下,范围n中有多个数,如果这个数量太小,ans就需要++,如果这个数量不算小,那ans的目前最低位就算是确定了,至于算不算小,看代码理解吧。。。

代码

class Solution {
public:
    int findKthNumber(int n, int k) {
        int ans=1;
        k--;
        long long t,ol,ne;
        while(k>0){
            t = 0;
            ol = ans;
            ne = ol + 1;
            while(ol <= n){
                t += min((long long)n+1,ne) - ol;
                ol *= 10;
                ne *= 10;
            }
            if(t <= k){
                ans ++;
                k -= t;
            }
            else{
                ans *= 10;
                k --;
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值