【编程题】【未知出处】字典序

字典序一般会出两种题目:

 

一、给一个字典序排列的数组,查找第k个元素

leetocde440:https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order/submissions/

输入n: 13,k: 2;输出10;解释:字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9]

1.迭代(与二方法一样,不需要判断result的长度,容易超出时间限制)

2.递归(与二方法一样,只是随时判断result的长度,到了长度就返回,很容易超出时间限制)

3.看作十叉链表的先序遍历(遍历0-9,遍历时设置left=1和right=2开始,每次遍历都加一,k-=1;在每一对儿leftright之间都要计算这中间<=n的数的个数num;如果num<k则k-=num继续遍历,否则说明我们要找的第k个就在此时的left和right之间;那么我们就把k-=1,leftright都乘10来继续本操作)(其中计算num的方法:设置一个leftright,)

class Solution(object):
    def findKthNumber(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: int
        """
        k -= 1 # 索引比真实个数小1,若k=1,则k=k-1=0直接输出cur=1
        cur = 1 # 依次遍历,取当前数和下一位数做判断,使用cur记录当前位置
        while k > 0: # 还差k位
            left, right = cur, cur + 1 # 判断l,r两个数之间有多少个数
            # 例如l=1,r=2,n=13,则我们得到step+=(min(2,14)-1=1)即[1,10,11,12,13,2]中的1
            # 接着l=10,r=20,step+=((min(20,14)-10)=4)即[1,10,11,12,13,2]中的10->13
            # 接着l=100,r=200,跳出循环
            # step = count(left, right, n)
            step = 0
            while left <= n:
                step += min(right, n+1) - left
                left, right = left*10, right*10
            # step = count(left, right, n)
            if step <= k: # 如果cur cur+1之间的个数没到k,则继续查看cur+1,cur+2
                k -= step
                cur = cur + 1
            else: # 如果cur cur+1之间的个数到k了,说明就在这之间,所以查找cur*10 (cur+1)*10
                k -= 1
                cur = cur*10
        return cur

4.前缀搜索

 

二、给定一个整数 n, 返回从 到 的字典顺序

leetocde386:https://leetcode-cn.com/problems/lexicographical-numbers/

两种方法,思路都是顺序的产生cur,例如输入n=13输出[1,10,11,12,13,2,3,4,5,6,7,8,9],当产生长度为n即结束。

1.迭代(遍历0 - n-1,每遍历一个cur就加入result内,这样循环结束得到的就是n长度的数组。当遍历到的数*10 <=n时,cur=cur*10,当cur>n时,若cur*10>n则cur=cur/10+1,否则cur+=1,加一操作后,若cur%10==0则cur/=cur。)

2.递归(遍历0 - 9,当遍历到的数<=n时,该数加入result,并且该数*10后传入该函数,重复遍历0-9) 相对来说递归更好理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值