蓝桥杯练习6——第k个数

问题描述

给定一个整数 nn ,请你在 1 到 n中找出字典序排序后第 k 个数字。例如,当 n 为 11 , k 为 3 时,字典序如下:

1,10,11,2,3,4,5,6,7,8,9

因此,第 3个数字是 11 。

输入格式

输入两个整数 n和 k,(1≤n,k≤10的9次方)(1≤n,k≤10的9次方)。

输出格式

输出一个整数,表示字典序排列后第 k个数字。

样例:

输入:13    2     输出:10

题目解读:

①字典序排序的本质是将输入的int看成字符串,依次进行排序 如n=11,从1到11排序,开头为1的数有1,10,11,依次比较这三个,1>10>11,所以字典序为1,10,11 ,再看1-11的数里2开头的只有一个,所以1>10>11>2如此排序.....

②从题目给的数据大小来看,不能用暴力解法(但下文给出了暴力解法,官网通过率20% T = T),因此我们想到决策树来模拟字典序排序。

暴力代码如下:

n,k = map(int,input().split())
def zidianxu(n, k):
    sort_num = sorted(str(i)for i in range(1,n+1))
    return sort_num[k-1]
ans = zidianxu(n,k)
print(ans)

模拟字典序排列的思路:

核心思想:逐位确定数字;从最高位到最低位逐位确认

计算子树的大小:对于当前的前缀,计算以该前缀开头的数字的数量

根据k和子树的大小 共同决定下一步:如果k<=当前前缀的字数大小,则进入该子树,否则跳过并继续处理下一个前缀。

重复操作以上步骤到确定所有位。时间复杂度为 O(1).

def find_kth_number(n, k):
    def count_prefix(prefix, n):
        """计算以 prefix 为前缀的数字的数量"""
        count = 0
        current = prefix
        next_prefix = prefix + 1
        while current <= n:
            count += min(n + 1, next_prefix) - current
            current *= 10
        """方便快速运算"""
            next_prefix *= 10
        return count

    result = 1
    k -= 1  # 将 k 转换为 0 索引
    while k > 0:
        # 计算以 result 为前缀的数字的数量
        cnt = count_prefix(result, n)
        if k >= cnt:
            # 如果 k 大于 cnt,则跳过该子树
            result += 1
            k -= cnt
        else:
            # 否则,进入该子树
            result *= 10
            k -= 1
    return result
n,k = list(map(int,input().split()))
ans = find_kth_number(n,k)
print(ans)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值