返回结果的字典序最小_354,字典序排数

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

例如,

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

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

答案:

 1public List lexicalOrder(int n) {
2    List res = new ArrayList<>(); 3    for (int i = 1; i 10; ++i) { 4        dfs(i, n, res); 5    } 6    return res; 7} 8 9public void dfs(int cur, int n, List res) {10    if (cur > n)11        return;12    res.add(cur);13    for (int i = 0; i 10; ++i) {14        dfs(10 * cur + i, n, res);15    }16}

解析:

解这题之前实现要明白什么是字典序,其实就是类似于字典一样,根据字母的顺序进行排列,我们先来看下面的图

aaa93e1e7f8ac257c08627cfbb2e00ff.png

我们可以把它看成有9棵树,每棵树的根节点的值分别是从1到9,并且每棵树都有10个子节点,并且每个子节点又会有10个子节点……

1,代码3到5行分别遍历这9棵树。

2,方法dfs对每棵树执行dfs(深度优先搜索),关于树的深度优先搜索可以参考前面介绍过的304,完全二叉树的节点个数这道题第二种解法使用的就是深度优先搜索(dfs)

我们仔细观察上面的图,字典序排数有一个规律,比如当n等于300的时候,结果是下面这样的

7498955640abec3f7a7b57672c80cc05.png

我们可以观察上面的数字,也可以查看最上面的图,就会发现这样一个规律。当数字curr小于n的时候,只要curr的个位数是9,那么他的下一个数就是(curr/10)+1(但要保证curr/10的个位数不能是9,如果是9就继续执行curr/10,直到curr/10的个位数不是9为止,比如199的下一个数是2),比如109的下一个是11,129的下一个是13一样。如果curr等于n,那么他的下一个数也是和上面同样的操作。理解了这点,代码就很容易写出来了

 1public List lexicalOrder(int n) {
2    List ans = new ArrayList<>(n); 3    int curr = 1; 4    for (int i = 1; i <= n; ++i) { 5        ans.add(curr); 6        if (curr * 10 <= n) { 7            curr *= 10; 8        } else { 9            while (curr % 10 == 9 || curr == n)10                curr /= 10;11            curr++;12        }13    }14    return ans;15}

重点是在第9到10行,如果curr的个位数是9或者curr等于n就要执行curr/10这步操作,直到curr的个位数不是9为止。

往期精彩回顾

327,最小高度树

310,二叉树的最近公共祖先

304,完全二叉树的节点个数

277,二叉树的前序遍历

256,二叉树的层次遍历

252,二叉树的中序遍历

a3c8c590bcf5d6613c6d6205e6a1d47f.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值