【问题标题】:Methods of decreasing algorythm complexity降低算法复杂度的方法
【发布时间】:2023-03-06 19:14:01
【问题描述】:

我正在尝试编写一个函数,该函数接受一个非负整数,并返回一个非负整数对列表,其值 - 当平方时 - 总和为给定整数。

例子:

  5  -->  [ [1, 2] ]
 25  -->  [ [0, 5], [3, 4] ]
325  -->  [ [1, 18], [6, 17], [10, 15] ]

我的解决方案在 IDE 中运行,但是当我将其提交给 codewars 时,我收到退出代码错误 139:致命错误:无效的表大小分配失败 - JavaScript 堆内存不足。 codewars 文档表明这是由于算法效率低下造成的。

最初我的解决方案包含一个嵌套循环,这会导致运行时间过长,但我已经重构了我的代码以删除它。尽管降低了复杂性,但我仍然遇到同样的错误。

有什么建议可以进一步降低复杂性吗?

const allSquaredPairs = (n) => {
//get array of all numbers between 0 and sqrt of n
let possibleNums = Array(n)
.fill()
.map((_, i) => {
  if ((i + 1) ** 2 <= n) return i + 1; //only numbers lesser than sqrt of n
})
.filter(n => n!=undefined)
possibleNums = [0, ...possibleNums];

const matchingPairs = [];
while (possibleNums.length){

    const num1 = possibleNums[0];
    const num2 = possibleNums[possibleNums.length-1];
    const sum = num1 ** 2 + num2 ** 2

    if (sum === n) matchingPairs.push([num1, num2]);
  
    if (sum > n ) possibleNums.pop()
    else possibleNums.shift()


  }
return matchingPairs;
};
console.log(allSquaredPairs(25));

【问题讨论】:

  • Array(n).map().filter() 将您已经很大的数组复制三份。从内存使用的角度来看,这不是有效的。虽然数组的前两个副本将符合垃圾回收条件,但它们将全部三个同时存在,从而增加您的峰值使用量。请正如其他答案已经说过的那样,在数组中预先创建所有可能的值并不是一种有效的方法。

标签: javascript node.js algorithm time-complexity space-complexity


【解决方案1】:

您的解决方案分配一个长度为 n 的数组,然后对其进行迭代。这意味着您的解决方案的内存需求会随着 n 的增加而线性增加。

您可以在不分配该数组的情况下实现这一点,这样无论 n 的值有多大,内存需求都是恒定的。

const examples = [
  { input:   5, output: [ [1, 2] ] },
  { input:  25, output: [ [0, 5], [3, 4] ] },
  { input: 325, output: [ [1, 18], [6, 17], [10, 15] ] },
  { input: Number.MAX_SAFE_INTEGER, output: [] }
];

function allSquaredPairs(n) {
  const matchingPairs = [];
  const smallestIntegerLargerThanSquareRootOfN = Math.ceil(Math.sqrt(n));
  let lowerBound = 0;
  let upperBound = smallestIntegerLargerThanSquareRootOfN;
  while (lowerBound < upperBound) {
    const sum = lowerBound ** 2 + upperBound ** 2;

    if (sum === n) {
      matchingPairs.push([lowerBound, upperBound]);
      lowerBound += 1;
    } else if (sum < n) lowerBound += 1;
    else if (sum > n) upperBound -= 1;
    else console.log("ERROR!")
  }
  return matchingPairs;
}

examples.forEach(({ input, output}) => console.log({ n: input, expected: JSON.stringify(output), "  actual": JSON.stringify(allSquaredPairs(input)) }));

作为一个兴趣点,我在函数的开头使用let whatever = new Array(n) 尝试了这个,对于最大安全整数测试用例,它抛出了RangeError: invalid array length。这与您看到的错误不同,但它确实说明了分配长度为 n 的数组会使事情变得复杂。

【讨论】:

  • 非常感谢您的回复。这真的解释得很清楚,我知道将来如何避免这个错误。
  • 太棒了!您如何获得“运行代码 sn-p”按钮?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 1970-01-01
  • 2021-03-30
相关资源
最近更新 更多