【LeetCode:递归与回溯】:1291.顺次数

1291.顺次数

难度:中等


我们定义「顺次数」为:每一位上的数字都比前一位上的数字大 1 的整数。
请你返回由 [low, high] 范围内所有顺次数组成的 有序 列表(从小到大排序)。

示例 1:

输出:low = 100, high = 300
输出:[123,234]
示例 2:

输出:low = 1000, high = 13000
输出:[1234,2345,3456,4567,5678,6789,12345]

提示:

10 <= low <= high <= 10^9


题解

方法一:穷举
/**
 * @param {number} shorter
 * @param {number} longer
 * @param {number} k
 * @return {number[]}
 */
var sequentialDigits = function(low, high) {
let res = [],
        index = 0;
    for (let i = 1; i <= 9; i++) {
        let n = i;
        for (let j = i + 1; j <= 9; j++) {
            n = n * 10 + j;
            if (n >= low && n <= high) {
                res[index++] = n;
            }
        }
    }
    //由于穷举后的数并不是由小到大,所以需要进行排序
    return res.sort(function(a,b){return a-b;});
};

方法二:剪枝
var sequentialDigits = function(low, high) {
    let res = []
    let lowLen = low.toString().length
    let highLen = high.toString().length
    for(let i=lowLen;i<=highLen;i++){
        for(let j=1;j<=10-i;j++){//剪枝:首位数不会大于10-i
            let str = ''
            let num = j
            str += num
            let k = i-1
            while(k--){
                num++
                str += num
            }
            let ans = parseInt(str)
            if(ans>=low && ans<=high){
                res.push(ans)
            }
        }
    }
    return res    
};

方法三:回溯
var sequentialDigits = function(low, high) {
  let res = [];
  for (let i = 1; i <= 8; i++) {
    backtrack(low, high, i, i)
  }

  res.sort((a, b) => a - b)
  return res
  function backtrack(low, high, val, j) {
    if (val >= low && val <= high) res.push(val);
    if (val > high) return
    if (j <= 8) {
      backtrack(low, high, val * 10 + j + 1, j + 1)
    }
  }
}


分析

由题可知顺次数即为每位数比前一位数大一,所求要符合定义域,则可以用穷举法进行遍历符合条件即可进入数组,由于进入的数并不是由小到大的,所以最后还需要进行排序。
穷举法虽然简单但毕竟太耗时,这里还可以进行剪枝

如要输出[100,1000]的顺次数,这里先用toString().length将数转换为字符串再求长度,即可以的到数据的位数,这里100是3位数,1000是4位数,即i>=3&&i<=4。
在100-1000之间都为三位数,最大的符合条件的顺次数为789,之后的都不存在,即首位数为7的789存在,而首位为8.9的都不存在,因此也没有必要遍历,因此可以剪枝,对于这里10-3(i)=7。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值