What a brilliant solution easily understandable! Here is some icing on the cake:

The dfs function already checked the condition (10*cur+i>n), before calling itself on this checked parameter. I think we can optimize by just checking one time.

Here is a solution inspired by your algorithms (185ms):

```
public List<Integer> lexicalOrder(int n) {
// DFS based solution:
List<Integer> res = new ArrayList<>();
for(int i = 1; i < 10 & i <= n; i++) {
dfs(i, n, res);
}
return res;
}
private void dfs(int m, int n, List<Integer> res) {
res.add(m);
for (int i = m * 10; i <= n && i < m * 10 + 10; i++) {
dfs(i, n, res);
}
}
```