字典序问题集合

Posted dream-flying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字典序问题集合相关的知识,希望对你有一定的参考价值。

1、关于数字的字典序

问题

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

例如,

给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] 。

请尽可能的优化算法的时间复杂度和空间复杂度。 输入的数据 小于等于 5,000,000。

 

分析:将问题转换为图集合问题,使用DFS遍历。

  (1)总共有9张图,1-9作为图的搜索的起始位置。

  (2)总起点开始深度优先遍历,将满足条件的值进行记录。

  (3)结束条件:节点值大于给定的结尾值。及n。

 

 1 public ArrayList<Integer> fun1(int n){
 2         ArrayList<Integer> list = new ArrayList<>();
 3         /*
 4         图的开始节点(1-9)
 5          */
 6         for(int i=1;i<10;i++){
 7             fun2(i,n,list);
 8         }
 9         return list;
10     }
11 
12     /*
13     深度优先遍历
14      */
15     public void fun2(int cur,int n,ArrayList<Integer> list){
16         if(cur>n){
17             return;
18         }else{
19             list.add(cur);//记录节点
20             for(int i=0;i<10;i++){
21                 int temp = cur*10+i;
22                 if(temp<n){
23                     fun2(temp,n,list);
24                 }else{
25                     return;
26                 }
27             }
28         }
29 
30     }

 

参考博客:https://blog.csdn.net/qq_41864967/article/details/88375912

 =======================================================

 

2、

问题

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

注意:1 ≤ k ≤ n ≤ 109。

 

分析: 依然可以使用DFS遍历解决问题,但为了满足时间条件,且只是找到第k小的数字,所以进行跳跃搜索。

  (1)跳跃搜索原理:将问题抽象为10叉树问题,首先横向计算相邻节点之间子节点的个数count,如果count<k,横向移动一个位置,k跟新为k = k-count;否则表明第k个值在子节点中,纵向移动一个位置,k更新为k = k-1.

  (2)结束条件:当k=0,当前值就为第k个值。

 

code:

 

 1 /*
 2     找到第k小的数字
 3      */
 4     public int findKthNum(int n,int k){
 5         int cur = 1;
 6         k = k-1;
 7         while(k>0){
 8             int step = getsonCount(n,cur,cur+1);
 9             if(step<k){
10                 k-=step;
11                 cur+=1; //横向移动
12             }else{
13                 k = k-1;
14                 cur*=10; //纵向移动
15             }
16         }
17         return cur;
18     }
19 
20     /*
21     计算相邻节点之间子节点的数量
22      */
23     public int  getsonCount(long n,long cur,long next){
24         int step = 0;
25         while(cur<n){
26             //控制被减数的边界。
27             step+=Math.min(n,next)-cur;
28             cur*=10;
29             next*=10;
30         }
31         return step;
32 
33     }

参考博客:https://blog.nowcoder.net/n/bdfaf75bcf7b4fac8b84dde60597a2c7

 

3、

问题:
多多鸡打算造一本自己的电子字典,里面的所有单词都只由a和b组成。
每个单词的组成里a的数量不能超过N个且b的数量不能超过M个。
多多鸡的幸运数字是K,它打算把所有满足条件的单词里的字典序第K小的单词找出来,作为字典的封面。

问题:链接:https://www.nowcoder.com/questionTerminal/061d419c7cea4c658ee0484654b11c3e?toCommentId=6222771
来源:牛客网

 

分析:同问题2的基本思路先相同,需要计算子树的数量。

  (1)子树问题:

分析:

以上是关于字典序问题集合的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 386 字典序排数[dfs 字典树] HERODING的LeetCode之路

子集生成与字典序

全排列 未按字典序

全排列的实现方法--递归&字典序

940C Phone Numbers

13 个非常有用的 Python 代码片段