题意:
给一个数n,按照字典顺序返回1-n。
分析:
什么是字典顺序呢?观察例子,分析是按位比较,先比较最高位。
我们按照人脑思维,是应该怎么选出排序呢?首先1,10,11,12...19这样但是还有1124,111167,11111187,测试数据很大。如果遍历会很难判断,所以考虑直接按照字典顺序去生成。
我们的遍历搜索是什么路径和规律呢?
举例子:1 10 100 1000 1001 1002....如果位数没有达到最高,就一直乘10,然后往后遍历10个数。到1009 按照数值顺序再往后就是1010,但是不对101的字典顺序在1010之前。所以1009之后是101然后是1010....1019然后是1020,又不对,应该是102然后是1021...
以上是举例子,我们接着来理论分析,我们要保证 a = b+1 一般情况,就是在前面的位数相同的情况下最后一位a为空,b为0(比如100和1000),或者a为n,b为n+1(比如104和105)。所以我们肯定是从1,100,1000这么扩大位数,然后最后一位从0-9,也就是说我们假设最大是4位数,那么前三位100就是最小的第四位从空到0到9完了以后我们第三位变成101,第四位又从空到0到9.
所以理论总结规律就是:一个数(比如1000)按照最低位开始处理,从0到9,然后次低位加1,最低位继续从空到0到9.
所以显然这是一个10叉树的先序遍历回溯搜索。
1 2 3 4 5 ...... 9
10 11 12 ....... 19
100 101....
这很好理解由于 空<0<1<2<...<8<9
所以我们要在高位确定的情况下比较低位,然后再改变次低位。。。。。
public class Solution {
List<Integer> list;
int n;
public List<Integer> lexicalOrder(int n) {
list = new ArrayList<>();
this.n = n;
for(int i=1; i<=9; i++) //因为没有根节点
helper(i);
return list;
}
private void helper(int i){
if(i > n)
return;
list.add(i); //来到当前结点,先放入(先序遍历)
for(int j=0; j<=9 ;j++){ //遍历下层结点
helper(i*10 + j); //回溯到当前层
}
}
}