题目:第k个数
主要为了学习数字的构造方法,如何快速求1~n中前缀为pre的数字的个数。
题目分析
一开始想的是把数字转化为字符串,然后丢给sort排序就行了,但是n太大了,会出现溢出问题。走到这里也从侧面反映了对所有的数字排序然后输出第k个数字的方法是不可取的,那么可不可以直接构造出第k个数字呢?
首先查找一下以1开头的数字个数,假设是在1~321里面寻找,那么以1开头的数字有1+10+100=111个,如果k=13<111,说明可以确定排序为k的数字的第一位就是1,那么再枚举下一位,下一位枚举以10开头的数字个数(这里1是已经确定的,但是呢1也是以1开头的,在枚举10的时候相当于舍弃了数字1,所以这里要k–,减掉数字1)有1+10=11个,假设k=12>11,那么说明排序为k的数字的第二位不是0,那么按照字典序枚举下一个数字,但是此时,我们可以把以10开头的数字舍弃掉了,所以k-=11,k=1。即查找以11开头的数字的个数有1+10=11个,假设k<11,说明排名为k的数字是以11开头的,然后再找110开头的数字的个数是1个,刚好和k相等,说明我已经找到那个数字了,就是110。
我们自己按照字典序排一下,看一看是不是,
1,10,101,102,103,104,105,106,107,108,109,11,110
可以看到110刚好排在第13的位置,说明我们上面分析的过程是对的。接下来看一下刚刚那个代码应该怎么写。
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();//数据范围为1~n
int k = scanner.nextInt();//找字典序排名为第k的数字
int cur = 1;//从以数字1开头的数字开始尝试
while(k > 0) {
long nums = get(n,cur,cur+1);//找以cur开头的数字的个数,具体怎么找后续讨论
if(k==nums&&k==1) {
//如果k和nums相等或者不相等,但是k=1了,都说明当前的数字cur就是我们要找的数字,
System.out.println(cur);
return;