降低算法复杂度的方法

Methods of decreasing algorythm complexity

我正在尝试编写一个接受非负整数和 returns 非负整数对列表的函数,这些非负整数对的值 - 当平方时 - 总和为给定整数。

示例:

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

我的解决方案在 IDE 中有效,但是当我将它提交给 codewars 时,我收到退出代码错误 139:致命错误:无效 table 大小分配失败 - 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));

您的解决方案分配一个长度为 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 的数组如何使事情复杂化。