题目描述:
LeetCode 440. K-th Smallest in Lexicographical Order
Given integers n
and k
, find the lexicographically k-th smallest integer in the range from 1
to n
.
Note: 1 ≤ k ≤ n ≤ 109.
Example:
Input: n: 13 k: 2Output: 10Explanation: The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.
题目大意:
给定整数n和k,计算从1到n的整数中字典序第k小的数。
注意: 1 ≤ k ≤ n ≤ 109
解题思路:
将整数1到n划分为3个区间分别求解:
区间1:字典序 ≤ n
区间2:首位数 = n的首位数,且字典序 > n
区间3:首位数 > n
Python代码:
class Solution(object):
def findKthNumber(self, n, k):
"""
:type n: int
:type k: int
:rtype: int
"""
if n < 10: return k
sn = str(n)
po = int('1' * len(sn))
fd = int(sn[0])
lo = (fd - 1) * po
mi = lo + self.calcMi(n)
hi = lo + self.calcHi(n)
if k > hi:
po /= 10
k -= hi
fc = (k - 1) / po + fd + 1
k += fd * po
elif k > mi:
return self.solveMi(9 * po / 10, n / 10 + 1, k - mi - 1)
else:
fc = (k - 1) / po + 1
return int(str(fc) + self.solve(9 * po / 10, k - (fc - 1) * po - 1))
def calcMi(self, n):
res = 1
mask = 10 ** int(math.log(n, 10))
while n > 9:
res += 1 + n % mask
n /= 10
mask /= 10
return res
def calcHi(self, n):
res = 1 + int('1' * (len(str(n)) - 1))
mask = 10 ** int(math.log(n, 10))
return res + n % mask
def solve(self, n, k):
if k == 0: return ''
if n <= 10: return str(k - 1)
po = int('1' * (len(str(n))))
fc = (k - 1) / po
rest = self.solve(9 * po / 10, k - fc * po - 1)
return str(fc) + rest
def solveMi(self, n, k, r):
if r <= n - k: return k + r
return self.solveMi(n / 10, k / 10 + 1, r - n + k)