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

posted @ 2017-04-25 10:03  panini  阅读(157)  评论(0编辑  收藏  举报