【问题标题】:Given an array of integers return positives, whose equivalent negatives present in it给定一个整数数组返回正数,其中存在等效的负数
【发布时间】:2018-09-28 06:28:52
【问题描述】:

我已经使用两个循环在 javascript 中实现了解决方案,下面是代码

function getNums(arr){
 var res = [];
 var found = {};
 var i, j;
 var arrLen = arr.length;

 for(i=0; i<arrLen; i++){
   if(!found.hasOwnProperty(arr[i])){
    for(j=0; j<arrLen; j++){
      if(arr[i]+arr[j] === 0){
        var num = arr[i];
        if(num > 0){
            res.push(num);
          found[num] = 1;
        }
      }
    }
   }
 }
 return res;
}

console.log(getNums[-1, -2, 0, -4, 1, 4, 6]); // Output: [1, 4]

其时间复杂度为 O(n2)。有人可以建议更好的解决方案/在上面进行改进以降低复杂性吗?

【问题讨论】:

  • 请添加数据arr和想要的结果res
  • 代码的用途是什么?看起来您正在尝试查找总和为 0 的所有数字对,但您仍然需要提及它。你不能指望人们阅读你的代码并猜出你的座右铭。

标签: javascript arrays algorithm


【解决方案1】:

您可以将数组添加到集合并过滤以包含在集合中。确定某物是否在集合中是常数时间:

let arr = [-1, 2, 3, 1 , 3, -3, 4, -6]
let s = new Set(arr)

// all positive numbers with corresponding negatives in the set
let filtered = arr.filter(item => item > 0 && s.has(-1 * item))
console.log(filtered)

另一种方法是对数组进行排序,然后将两个指针沿数组向上移动以进行匹配。但是,结果将被排序,但可能与原始数组的顺序不同:

let arr = [-2, -3, 2, 5, 3, 1, -6, 2, -5]
arr.sort()

// get startig indexes
let i = 0, j = arr.findIndex(n => n > 0)
let res = []
if (j > -1) { // only if there are positive numbers in the array
    while(arr[i] < 0 && j < arr.length){
        if (-1 * arr[i] === arr[j]){
            res.push(arr[j++])
        } else if(-1 * arr[i] > arr[j]){
            j++
        } else if(-1 * arr[i] < arr[j]){
            i++
        }
    }
}
console.log(res)

【讨论】:

  • 请尝试[1, 2, -3, -4, 2, 3, 4, 4, -4, 4]Set 不知道计数。
  • @NinaScholz,结果我得到了[ 3, 4, 4, 4 ]。这就是我所期望的结果——数组中存在负数的所有正数。也许我误解了这个问题。
  • 当我阅读这个问题时,它应该有成对的负值和正值。
  • @NinaScholz,是的,我也能看到。可能会更清楚。
【解决方案2】:

您可以通过计数值来采用 循环方法。

function getNums(array) {
    var count = Object.create(null),
        result = [];

    array.forEach(v => {
        if (count[-v]) {
            result.push(Math.abs(v));
            count[-v]--;
            return;
        }
        count[v] = (count[v] || 0) + 1;
    });
    return result;
}

console.log(getNums([1, 2, -3, -4, 2, 3, 4, 4, -4]));

【讨论】:

    【解决方案3】:

    在否决之前...这个答案不是最短的 javascript 代码,而是算法 - 我认为这是最初的问题。

    摆脱嵌套循环的一种方法是使用更多内存来存储中间结构。在您的情况下,您不仅要存储“found”标志,还要存储负值、正值,以便在每次迭代时都可以设置 found 标志。然后您还使用“found”标志来防止第二次添加结果。

    var f = function(arr) {
      let hash = {};
      let res = [];
      for (var i = 0; i < arr.length; i++) {
          // put value into the hash map  for future use
          hash[arr[i]] = arr[i];
          var absVal = Math.abs(arr[i]);
    
          // if value is not 0 AND if it has not been found yet (x+value hash) AND if both negative and positive values are present
          if( arr[i] !== 0 && !hash["x"+absVal] && (hash[arr[i]] + hash[-arr[i]] === 0)){
    
              // then set the found hash to  true
              hash["x"+absVal] = true;
    
              // and push to the resut
              res.push(absVal);
          }
      }
    
      // return the result
      return res;
    }
    

    【讨论】:

      【解决方案4】:

      另一种解决方案是使用过滤器并包含经过良好优化的原型函数。

      const getNums = (arr) => arr.filter((num, index) => num > 0 && !arr.includes(num, index + 1) && arr.includes(-num));
      

      【讨论】:

      • 以-200到6000整数的数组为特征,执行速度大约快两倍。
      猜你喜欢
      • 2015-07-19
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-06
      • 1970-01-01
      相关资源
      最近更新 更多