给定 开始 和 结束为止,返回这段数字区间中的 N*10 + 1

阿古达木
  • 417

比如 fn(43, 72) 返回 [51,61,71]

回复
阅读 1.3k
6 个回答

最简单的就是 for 循环从 43 到 72,步长为 1,判断 i % 10 是否等于 1,是就留下,不是就下一轮循环。

但你会发现每 10 轮中有 9 次都是可以跳过的,那就把步长改为 10 好了,这样循环里面还省去了除余数的运算开销,那么要点就在于怎么找开始位置。问题变成“给定一个数字,找到离它最近、且大于等于它的 10N+1 数字”,即 f(43) = 51

还是先跟 10 取余,余数如果是 1,那就不用找了,就是它自己;如果比 1 小,那么最近的且比它的大就 +1-m(m 即余数。其实 +1 就行了,因为比 1 小的只有 0 了,但如果你哪天想换成 10N+2 这块改起来容易);如果比 1 大,就是 +11-m。就是基本的四则运算问题,应该能看懂吧。

整理一下思路:

function fn(start, end) {
    const m = start % 10;
    if (m !== 1) {
        start = (m < 1) ? (start + 1 - m) : (start + 11 - m)
    }

    const result = [];
    for (let i = start; i <= end; i += 10) {
        result.push(i);
    }

    return result;
}

image.png

P.S. 题外话,其实这两种办法最后时间复杂度都是 O(n),所以说时间复杂度的相同或高低并不意味着最后耗时就一定有所相同或不同。

image.png

fn = (m, n, p = 10, t = 1) => {
  let i = Math.floor(m / p) * p + (m % p > t ? p + t : t)
  let arr = []
  for (; i < n; i += p) arr.push(i)
  return arr
}
function fn(s1, s2) {
  let arr = []
  for(let i = s1; i <= s2; i++) {
    !(i % 10) && arr.push(i + 1)
  }
  return arr
}
let a = fn(42, 73)
console.log(a)
function* enumInRange(min, max) {
    let begin = min - min % 10 + 1;
    if (begin < min) { begin += 10; }
    for (let n = begin; n <= max; n += 10) {
        yield n;
    }
}

const result = [...enumInRange(43, 72)];
console.log(result);
  1. 找到起始数,就是 min 向下取到整 10 之后加 1 的数
  2. 判断这个数是否在范围外,如果是,加个步长,也就是 10
  3. 在范围内以 10 为步长循环,命中的数都是需要的
const fn = (a, b) => {
    const start = Math.floor(a / 10) + (a % 10 > 1 ? 1 : 0)
    const over = Math.floor(b / 10) - (b % 10 < 1 ? 1 : 0)
    return Array.from({length: over - start + 1}).fill(0).map((v, index) => `${start + index}1`)
}
你知道吗?

宣传栏