【问题标题】:how to improve performance of nested for loops when comparing values in an array比较数组中的值时如何提高嵌套for循环的性能
【发布时间】:2020-02-14 23:03:58
【问题描述】:
var twoSum = function(nums, target) {
  for(let i = 0; i < nums.length; i++){
    for(let j = i + 1; j < nums.length; j++){
      if(nums[i] + nums[j] === target){
        return [nums.indexOf(nums[i]), nums.lastIndexOf(nums[j])]
      }
    }
  }
}
function([3,5,3,7,2], 9) //It should return [3, 4] since 7 + 2 = 9

这是一个 Javascript 函数,它使用嵌套的 for 循环遍历数字数组,并找到一对求和后等于目标并返回其索引的对。由于它有一个嵌套的 for 循环,我相信它具有 O(n^2) 或二次时间复杂度,我想知道是否有更快的方法来做到这一点。我只是想获得第一次通过的解决方案,然后对其进行改进。 ???提前致谢!

【问题讨论】:

  • 不要使用数组,而是使用适当的查找数据结构。
  • @Bergi 棘手的是数组允许重复,大多数查找结构不允许。
  • 它对您的复杂性问题没有帮助,但您不需要调用 indexOf,因为 i 和 j 已经是索引
  • 对数组进行排序,然后可以使用二分查找target - nums[i]
  • @Barmar 但是在这种情况下,我们不在乎重复,对吗?

标签: javascript arrays nested-loops


【解决方案1】:

创建一个将每个元素映射到其最后一个索引的对象。然后循环遍历每个元素,看看target - element 是否在具有不同索引的对象中。

function twoSums(nums, target) {
  const last_index = {};
  nums.forEach((num, i) => last_index[num] = i);
  for (let i = 0; i < nums.length; i++) {
    const diff = target - nums[i];
    if (diff in last_index && last_index[diff] != i) {
      return [i, last_index[diff]];
    }
  }
}

const list = [3,5,3,7,2];
console.log(twoSums(list, 9));
console.log(twoSums(list, 6));
console.log(twoSums(list, 15));

查找一个对象属性是O(1),所以这个算法是O(n)。

【讨论】:

  • 复杂度还是O(n*n)
  • 不,它是 O(n)。属性查找是 O(1)。
  • 哦,是的,这是正确的,但是如果只有一个 3 而您需要得到 6 的总和呢?您可能还需要存储频率?
  • 问题是关于寻找元素对。他的代码从不重复使用相同的元素,它们总是不同的。
  • i 将是第一个索引。这就是为什么我检查它们不相等的原因,它可以防止使用相同的元素两次。
【解决方案2】:

你可以使用嵌套的map():

var twoSum = (nums, target)=> {
  //  map trough list for first number
  nums.map(
  	(val1, index1)=>
    {
      // map through list again for second number to compare to number returned from first map at each instance
      nums.map((val2, index2) =>
      {
      //  Ensure that index1 and index2 are not the same before you compare
        if(index1 != index2 && (val1 + val2 === target))
        {
          alert([index1, index2]);
          return [index1, index2];
        }
      });
    }
  );
}

twoSum([3,5,3,7,2], 9) //It should return [3, 4] since 7 + 2 = 9

注意:请记住,除非未找到匹配项,否则这不会遍历所有项目。一旦找到匹配项,函数就会返回并退出。

【讨论】:

  • 这也是 O(n^2)。您也不要阻止两次使用相同的元素,并且在找到解决方案时不要停止。
  • return 找到解后退出函数,记住@Barmar.
  • 你只是从被映射的函数中返回,而不是退出循环。
  • 没有办法跳出map() 循环。
  • jsfiddle.net/sLpb2g58 逆势而上,你可以突破地图。
猜你喜欢
  • 2021-12-01
  • 2012-11-25
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多