-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
LexicographicalNumbers.cpp
109 lines (97 loc) · 3.56 KB
/
LexicographicalNumbers.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Source : https://leetcode.com/problems/lexicographical-numbers/
// Author : Hao Chen
// Date : 2016-08-23
/***************************************************************************************
*
* 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.
***************************************************************************************/
class Solution {
//Solution 1: convert the int to string for sort, Time complexity is high (Time Limited Error)
public:
vector<int> lexicalOrder01(int n) {
vector<int> result;
for (int i=1; i<=n; i++) {
result.push_back(i);
}
sort(result.begin(), result.end(), this->myComp);
return result;
}
private:
static bool myComp(int i,int j) {
static char si[32]={0}, sj[32]={0};
sprintf(si, "%d\0", i);
sprintf(sj, "%d\0", j);
return (strcmp(si, sj)<0);
}
//Solution 2 : using recursive way to solution the problem, 540ms
public:
vector<int> lexicalOrder02(int n) {
vector<int> result;
for (int i=1; i<=n && i<=9; i++) {
result.push_back(i);
lexicalOrder_helper(i, n, result);
}
return result;
}
private:
void lexicalOrder_helper(int num, int& n, vector<int>& result) {
for (int i=0; i<=9; i++) {
int tmp = num * 10 + i;
if (tmp > n) {
break;
}
result.push_back(tmp);
lexicalOrder_helper(tmp, n, result);
}
}
//Solution 3: no recursive way, but the code is not easy to read
public :
vector<int> lexicalOrder03(int n) {
vector<int> result;
int curr = 1;
while (result.size()<n) {
// Step One
// ---------
//Adding all of the possible number which multiply 10 as much as possible
// such as: curr = 1, then 1, 10, 100, 1000 ...
// curr = 12, then 12, 120, 1200, ...
for (; curr <= n; curr*=10 ) {
result.push_back(curr);
}
// Step Two
// ---------
// After find the number which multiply 10 greater than `n`, then go back the previous one,
// and keep adding 1 until it carry on to next number
// for example:
// curr = 100, then we need evalute: 11,12,13,14,15,16,17,18,19, but stop at 20
// curr = 230, then we need evaluate: 24,25,26,27,28,29, but stop at 30.
curr = curr/10 + 1;
for (; curr <= n && curr % 10 != 0; curr++) {
result.push_back(curr);
}
// Step Three
// ----------
// Now, we finished all of the number, we need go back for next number
// Here is a bit tricky.
//
// Assuming the n is 234, and Step One evaluted 190, and Step Two, evaluted 191,192,...,199
// Now, the `curr` is 200, and we need start from 2 instead of 20, that's why need keep dividing 10
for (; curr%10 == 0; curr/=10);
}
return result;
}
//start point
public:
vector<int> lexicalOrder(int n) {
srand(time(NULL));
if (rand()%2)
return lexicalOrder02(n); // recursive way 560ms
else
return lexicalOrder03(n); // non-recursive way, 460ms
}
};