算法小知识-----04.18-----字典序排数

126 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

连续一个月的单休,属实是身心俱疲

字典序排数

该题出自力扣的386题 —— 字典序排数【中等题】

审题

给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。
你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。

image.png

  • 根据题意,给出一个整数,需要对[1,n]的范围整数进行字典序排数
  • 首先,需要知道什么是字典序排序,字典序区别于整数排序,例如:123和23的排序方式,字典序的话需要转换成"123","23";对于字典序,是一种字符串的排序方式。先按首字符排序,如果首字符相同,再按第二个字符排序。
  • 基于这种规律,我一开始是想用Collection.sort(list)的,因为本身就是作为字典序去排列的。但是考虑到空间复杂度需要O(1),然而这种做法需要先new 一个String 类型的List,去存储[1,n]的整数,再进行排序,然后再循环塞进List的Integer类型。这就至少需要O(n)的空间复杂度了
  • 因此最终还是选择了使用循环 + 条件的方式
    • 定义出一个List 的变量集合去装载结果
    • 定义初始值num = 1
    • 循环遍历 1 到 n
      • 如果num *10 <= n则 乘10(因为字典序的话就是比较第一个字符 + 第二个字符,因此这里先从第二个字符为0开始)
      • 否则,判断是否余10 == 9 (也就是是否为最后一位),或者 +1 > n(最后一位)
      • 返回整个LIST
  • 时间复杂度为O(n)
  • 空间复杂度为O(1)

编码

class Solution {
    public List<Integer> lexicalOrder(int n) {
        List<Integer> list = new ArrayList<>();
        int number = 1;
        for(int i =0;i<n;i++){
            list.add(number);
            if(number *10 <=n){number *=10;}
            else {
                while(number %10 ==9 || number +1 >n){
                    number/=10;
                }
                number ++;
            }
            
        }
        return list;
    }
}

image.png