字典序问题集合
Posted dream-flying
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字典序问题集合相关的知识,希望对你有一定的参考价值。
1、关于数字的字典序
问题:
给定一个整数 n, 返回从 1 到 n 的字典顺序。
例如,
给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] 。
请尽可能的优化算法的时间复杂度和空间复杂度。 输入的数据 n 小于等于 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)子树问题:
分析:
以上是关于字典序问题集合的主要内容,如果未能解决你的问题,请参考以下文章