Leetcode 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.
題意分析
給定一個數n,將1到n之間的數按照字典順序輸出。
解法分析
首先要搞清楚字典順序的含義,字典順序準則有兩條,第一條是如果一個序列是另一個序列的前部,則短的序列一定在長序列之前,如ab在abc之前,如果兩個序列有對應位不相同,不管兩個序列長短如何,只需要比較第一個不相同字符的前後順序,如134>1245677。本題採用兩種方法來解,一是直接構造法,二是深度優先搜索。
-
直接構造
由於1一定是第一個元素,所以可以將temp初始化爲1,外層循環按照res的長度進行。對1乘10,得到10,如果沒有超過n,則本輪循環結束,進入下次循環,並把10放入res,多次乘十,直到不能再大,此時判斷temp+1是否超過n,如果超過了,就整體除以10,不然就直接加一,最後判斷是否進位,有進位就把0去掉。C++代碼如下:
class Solution {
public:
vector<int> lexicalOrder(int n) {
int temp=1;
int i;
vector<int> res(n,1);
for(i=0;i<n;i++){
res[i]=temp;//1 should be added,so do this step first
if(temp*10<=n){//先判斷,之後再賦值
temp*=10;
}
else{
if((temp+1)>n){//先做判斷,再賦值
temp/=10;
}
temp++;
while(temp%10==0)
temp/=10;
}
}
return res;
}
};
-
深度優先搜索
通過字典序的特點可以看出,如果開頭爲1,則以1位樹根,0-9爲下一層節點,每一個節點又以0-9位子節點,這樣利用深度優先搜索就能得到相應字典順序,對於大於n的情況可以在搜索中剪去。外層循環遍歷1-9作爲開頭數字。C++代碼如下:
class Solution {
private:
int N;
vector<int> res;
public:
void dfs(int k){
if(k>N)
return;
res.push_back(k);
for(int i=0;i<=9;i++){
if((10*k+i)>N)
return ;
dfs(10*k+i);
}
}
vector<int> lexicalOrder(int n) {
N=n;
for(int i=1;i<=9;i++)
dfs(i);
return res;
}
};