首页 > leetcode-440 字典序的第K小数字

leetcode-440 字典序的第K小数字

给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字。

注意:1 ≤ k ≤ n ≤ 10^9。

示例 :

输入:

n: 13

k: 2

输出: 10

解释:

字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。

字典排序数的实现可以参考leetcode-386

字典排序数即10叉树的形态,数值排列按照 字符串首字母的ascii码值进行排序

那么数值的字典序即为一个十叉树,比如以1为树顶的树状形式如下:

1



10 11 … 19



100 101 102…109

可以看到第一层第一个数 1 和第二层之间的计算方式:

1 *10 + (1…9)

第二层 第一个数 100 和第三层之间的计算方式

10*10 + (1…9)

此时我们要在n (1…10^9)的范围内找到第k大的数。

如果一个个查找,势必效率低下。那么可以缩短查找路径,方式如下:

  1. 获取以1开头和以2开头数值之间的 数值个数,和k值比较

    如果大于k,说明在以1开头之下的某一层中,即可增加层数继续在下一层10…11之间的数值个数,缩短k的路径

    如果小于k,那么需要更换子树,更改为以 2 开头的字典树
  2. 计算的数值个数需要在n的范围内,同时每当层数递增时需缩减k的数值,相当于重新找到了计算起点

实现如下:

/*计算[n,n+1]范围内满足小于max的字典数的个数*/
int getCount(long n, int max) { int res = 1;long left = n *10 + 0;//n下一层的第一个数long right = n *10 + 9;//n下一层的第10个数while(left <= max) { if (max <= right) {  //max在[n,n+1]之间res += (max - left + 1);} else { res += (right - left + 1);}left = left * 10 + 0;//继续递增层数right = right *10 + 9;}return res;
}int findKthNumber(int n, int k) { //return cur;long l = 1;long r = 9;while(k) { for (long i = l;i <= r; ++i) { int f = getCount(i, n);//获取[i,i+1]之间的字典数的个数,并和k进行比较//发现k大于上一个子树中字典树数的数值个数,那么更换子树iif (f < k) { k -= f;}else { //否则,继续深度搜索,缩减k的范围并进入到当前子树的下一层k --;if(k == 0) return i;l = i *10 + 0;r = i *10 + 9;break;}}}return 0;
}

更多相关:

  • 找规律题 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的: 1/1 1/2 1/3 1/4 1/5 … 2/1 2/2 2/3 2/4 … 3/1 3/2 3/3 … 4/1 4/2 … 5/1 … … 我们以Z字形给上表的每一项编号。第一项是1/1,然后是1/2,2/1,...

  • 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的,且key必须是可哈希的。可哈希表示key必须是不可变类型,如:数字、字符串、元组。 字典(dictionary)是除列表意外python之中最灵活的内...

  • 1、函数式编程语言有:lisp,hashshell,erlang等。 2、在函数中的参数,有一一对应的,也有指定模式的,还有使用能数组。如*argp(元组),**argp(字典)。 3、在pyphon语言中有一些内置的函数,如abs求绝对值,eval()转字典。 转载于:https://www.cnblogs.com/lyzf...