leetcode 面试题 16.11. 跳水板

134 阅读2分钟

你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为shorter,长度较长的木板长度为longer。你必须正好使用k块木板。编写一个方法,生成跳水板所有可能的长度。

返回的长度需要从小到大排列。

示例 1

输入:
shorter = 1
longer = 2
k = 3
输出: [3,4,5,6]
解释:
可以使用 3 次 shorter,得到结果 3;使用 2 次 shorter 和 1 次 longer,得到结果 4 。以此类推,得到最终结果。

提示:

  • 0 < shorter <= longer
  • 0 <= k <= 100000

我的第一次尝试:

/**
 * @param {number} shorter
 * @param {number} longer
 * @param {number} k
 * @return {number[]}
 */
var divingBoard = function (shorter, longer, k) {
  let arr = new Array(k).fill(shorter);
  let tempArr = new Set();
  const len = arr.length || -1;
  for (let i = 0; i <= len; i++) {
    const sum = arr.reduce((a, b) => a + b);
    tempArr.add(sum);
    arr[i] = longer;
  }
  return [...tempArr];
};

结果运行的时候出现了超时,莫名其妙,我用浏览器运行都挺快的。经过我打算执行时间,发现执行 reduce 过程耗时最长,所以我打算优化这一过程。我想到其实就是多少个 shorter 之和或者多少个 longer 之和,于是就得到了下面的代码:

var divingBoard = function (shorter, longer, k) {
  let tempArr = new Set();
  const len = k || -1;
  let m = k,
    n = 0;
  for (let i = 0; i <= len; i++) {
    const sum = m * shorter + n * longer;
    tempArr.add(sum);
    m-- , n++;
  }
  return [...tempArr];
};

这样就顺利通过了,但是运行总耗时也花费了 188s ,仍然比较耗时。当前的算法时间复杂度是 O(k) ,空间复杂度也是 O(k)。由于我在乎的是执行速度,那么我重点看怎么提高执行效率。

经过我的努力,成功的将时间减少了 30s

/**
 * @param {number} shorter
 * @param {number} longer
 * @param {number} k
 * @return {number[]}
 */
var divingBoard = function (shorter, longer, k) {
  if (k === 0) {
    return [];
  }
  let tempArr = [];
  for (let m = k, n = 0; n <= k; m-- , n++) {
    const sum = m * shorter + n * longer;
    if (tempArr[tempArr.length - 1] !== sum) {
      tempArr.push(sum);
    }
  }
  return tempArr;
};

以前慢主要是从 SetArray 也比较耗时,因为相较于上面的算法,这次的算法去重自己做的,当然这取决于数组的值是一个递增的过程,所以即便有重复也是跟前一个元素有关系。现在耗时为: 152s,我感觉还能减少,在我这个算法的基础上。我再思考思考。


来源:力扣(LeetCode)