zoukankan      html  css  js  c++  java
  • 386. Lexicographical Numbers

    题目:

    Given an integer n, return 1 - n in lexicographical order.

    For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9].

    Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000.

    链接:https://leetcode.com/problems/lexicographical-numbers/#/description

    4/17/2017

    自己的做法,超时

    通过变为list of string,针对string排序,再转为list of integer

     1 public class Solution {
     2     public List<Integer> lexicalOrder(int n) {
     3         List<String> l = new ArrayList<String>();
     4         for (int i = 1; i <= n; i++) {
     5             l.add(Integer.toString(i));
     6         }
     7         Collections.sort(l);
     8         List<Integer> ret = new ArrayList<Integer>();
     9         for (int i = 0; i < l.size(); i++) {
    10             ret.add(Integer.parseInt(l.get(i)));
    11         }
    12         return ret;
    13     }
    14 }

    只好看别人的算法,真的是很厉害

    https://discuss.leetcode.com/topic/55184/java-o-n-time-o-1-space-iterative-solution-130ms

    加入某一值v之后,先判断v*10在不在范围内,若有,更新v接着计算10倍的值;若没有,并且v不是以9结尾,如果v+1在n的范围内就更新v值为v+1;若v是以9结尾,那么从尾向前找第一个不是9的位,然后将其+1作为新的v

    The basic idea is to find the next number to add.
    Take 45 for example: if the current number is 45, the next one will be 450 (450 == 45 * 10)(if 450 <= n), or 46 (46 == 45 + 1) (if 46 <= n) or 5 (5 == 45 / 10 + 1)(5 is less than 45 so it is for sure less than n).
    We should also consider n = 600, and the current number = 499, the next number is 5 because there are all "9"s after "4" in "499" so we should divide 499 by 10 until the last digit is not "9".
    It is like a tree, and we are easy to get a sibling, a left most child and the parent of any node.

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

    用DFS的做法,n叉树的DFS。个人比较喜欢的思路。

    注意:2次循环是不同的,第一次从1开始,第二次是0开始。第一次是输出的第一个值,也是因为heading 0是不对的,在dfs里面代表的是非首位的选择,所以是从0到9

    https://discuss.leetcode.com/topic/55377/simple-java-dfs-solution

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

    跟第一种解法类似,第11,12行的意思是比如n=23,当23做完之后下一个值应该是3,跟第14行很像,都是需要前进到之前的某个比自己小的值

    https://discuss.leetcode.com/topic/55131/ac-200ms-c-solution-beats-98

     1 class Solution {
     2 public:
     3     vector<int> lexicalOrder(int n) {
     4         vector<int> res(n);
     5         int cur = 1;
     6         for (int i = 0; i < n; i++) {
     7             res[i] = cur;
     8             if (cur * 10 <= n) {
     9                 cur *= 10;
    10             } else {
    11                 if (cur >= n) 
    12                     cur /= 10;
    13                 cur += 1;
    14                 while (cur % 10 == 0)
    15                     cur /= 10;
    16             }
    17         }
    18         return res;
    19     }
    20 };

    Python大哥的贴子可以了解很多Python的细节,他的贴子和跟别人的讨论

    https://discuss.leetcode.com/topic/55090/python-with-sorting

    https://discuss.leetcode.com/topic/55118/python-with-dfs

    以tree pre-order traversal来解题:

    https://discuss.leetcode.com/topic/55196/recursive-java-solution-using-pre-order-traversal

     1 public class Solution {
     2     public List<Integer> lexicalOrder(int n) {
     3         List<Integer> res = new ArrayList<>();
     4         lexicalOrderHelper(res, 1, n);
     5         return res;
     6     }
     7 
     8     private void lexicalOrderHelper(List<Integer> res, int i, int n) {
     9         if(i > n) return;
    10         res.add(i);
    11         lexicalOrderHelper(res, i * 10, n);
    12         if(i + 1 <= (i / 10) * 10 + 9) lexicalOrderHelper(res, i + 1, n);
    13         else return;
    14     }
    15 }

    更多讨论:

    https://discuss.leetcode.com/category/508/lexicographical-numbers

  • 相关阅读:
    epoll精髓 C++ 技术中心 C++博客
    【找茬】split string 力为的技术博客 C++博客
    不谈技术~蛇年,我回来了!
    不说技术~希望所有人都好好的
    DDD~充血模型和失血模型
    基础才是重中之重~何为原子化操作
    DDD~概念中的DDD
    策略模式
    windows句柄和消息技术
    观察者模式2(observer)
  • 原文地址:https://www.cnblogs.com/panini/p/6726683.html
Copyright © 2011-2022 走看看