一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情 。
给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。
你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。
示例 1:
输入:n = 13
输出:[1,10,11,12,13,2,3,4,5,6,7,8,9]
示例 2:
输入:n = 2
输出:[1,2]
提示:
深度优先搜索
题目要求设计一个时间复杂度为 且使用 额外空间的算法,因此我们不能使用直接排序的方法。
那么对于一个整数 ,它的下一个字典序整数对应下面的规则:
- 尝试在 后面附加一个零,即 ,如果 ,那么说明 是下一个字典序整数;
- 如果 或 ,那么说明末尾的数位已经搜索完成,退回上一位,即 ,然后继续判断直到 且 为止,那么 是下一个字典序整数。
字典序最小的整数为 ,我们从它开始,然后依次获取下一个字典序整数,加入结果中,结束条件为已经获取到 个整数。
var lexicalOrder = function(n) {
const ret = [];
let number = 1;
for (let i = 0; i < n; i++) {
ret.push(number);
if (number * 10 <= n) {
number *= 10;
} else {
while (number % 10 === 9 || number + 1 > n) {
number = Math.floor(number / 10);
}
number++;
}
}
return ret;
};
字典序,找规律,递归
数字的字典序是这样定义的: 单字符比较的顺序是0<1<...<9 多位字符时从前至后按位比较,直到某一位分出大小后停止 上一条分不出大小时,长度短的字典序靠前
根据字典序的定义,以及对样例输出找规律,可以发现当已有数字num时,可以按顺序展开与num相关的后续数字: a, 尾部添加0,即num*10,并递归处理 b, 自身加1,即num+1,并递归处理(当num以9结尾时,跳过这一步)
var lexicalOrder = function(n) {
return dfs(n)
};
function dfs(target, prev = 0, list = []) {
for(let i = 0; i < 10; i++){
if(i === 0 && prev === 0) continue
let num = prev * 10 + i
if(num > target) continue
list.push(num)
dfs(target, num, list)
}
return list
}