有效的方法来展平数组元素(不是整个数组)的javascript

时间:2015-11-05 23:46:30

标签: javascript algorithm

我正在练习算法并且遇到了一个问题,你给了一个数组,你想要返回一个数组,其中除了该索引处的数字之外的所有其他数字的乘积。所以[1,2,3,4]将返回[24,12,8,6]。我的方法是循环遍历数组,制作副本,然后拼接出当前索引,然后将该副本推送到输出数组。

function getAllProductsExceptAtIndex(arr) {
  var productArr = [];

  for (var i = 0; i < arr.length; i++) {
    var copy = arr.slice();
    copy.splice(i, 1);
    productArr[i] = copy;
  }

  // return productArr;
  for (var j = 0; j < productArr.length; j++) {

    reduce(productArr[j]); 

  }
}

getAllProductsExceptAtIndex([1, 2, 3]); ---> productArr = [[2,3],[1,3],[1,2]]

现在你有一个输出数组,其中包含正确的值,只需要减少&#34;减少&#34;乘以一个值。现在简化是常规和所有,但在这种情况下,我试图提高效率(时间),因此循环数组并减少将是o(n)平方,因为reduce在内部使用for循环。我想写一个帮助减少,但如果你在循环中调用它仍然是o(n)平方?

什么是一种更有效的方法来将productArr的每个索引中的元素相乘,然后展平?我宁愿不在解决方案中使用除法。

3 个答案:

答案 0 :(得分:2)

非常简单:

&#13;
&#13;
function getAllProductsExceptAtIndex(arr) {
  var product = arr.reduce(function(prev, curr) { return prev * curr; });
  return arr.map(function(v) { return product / v; });
}

console.log(getAllProductsExceptAtIndex([1, 2, 3, 4]));
&#13;
&#13;
&#13;

计算整个数组的乘积,然后将每个值映射到product / current_value,这是数组其余部分的乘积。

如果您想要一个不使用除法的解决方案,您可以将reduce放在map内并忽略当前项目:

&#13;
&#13;
function getAllProductsExceptAtIndex(arr) {
  return arr.map(function(v, i) {
    return arr.reduce(function(prev, curr, j) {
      return i != j ? prev * curr : prev;
    });
  });
}

console.log(getAllProductsExceptAtIndex([1, 2, 3, 4]));
&#13;
&#13;
&#13;

最后,以代码复杂化为代价,我们可以在 O(n) 时间内完成:

&#13;
&#13;
function getAllProductsExceptAtIndex(arr) {
  if(arr.length === 0)
    return [];

  var i, products = [1];
  for(i = 0; i < arr.length - 1; i++) {
    products.push(products[i] * arr[i]);
  }

  for(var t = 1; i >= 0; i--) {
    products[i] *= t;
    t *= arr[i];
  }

  return products;
}

console.log(getAllProductsExceptAtIndex([1, 2, 3, 4]));
&#13;
&#13;
&#13;

我们在第一遍中计算每个索引左侧的产品,但我们使用之前的计算( O(n))。然后我们向后做同样的事情,向右计算产品并乘以我们之前计算的值。有一个常数&#34; 1 &#34;插入边缘案例 - &#34;产品&#34;共0个项目([0]左侧,[length - 1]右侧)。

要了解其工作原理,请考虑通过任何项目右侧所有项目的产品复制左侧所有项目的产品意味着什么。

答案 1 :(得分:2)

此解决方案已从Interview Cake转换为JS。强烈建议学习算法:https://www.interviewcake.com/

&#34;要查找除每个索引处的整数之外的所有整数的乘积,我们将贪婪地浏览两次列表。首先,我们在每个索引之前得到所有整数的乘积,然后我们返回以获得每个索引之后的所有整数的乘积。

当我们在每个索引之前和之后乘以所有产品时,我们得到答案 - 除了每个索引处的整数之外的所有整数的乘积!&#34;

function productOfInts(arr){
  var productOfAllExceptIndex = new Array(arr.length);
  var productSoFar = 1;

  for (var i = 0; i < arr.length; i++){
    productOfAllExceptIndex[i] = productSoFar;
    productSoFar *= arr[i];
  }

  productSoFar = 1;

  i -= 1;

  while (i >= 0){
    productOfAllExceptIndex[i] *= productSoFar;
    productSoFar *= arr[i];
    i--;
  }

  return productOfAllExceptIndex;
}

答案 2 :(得分:-1)

对于数组/对象操作,您可以使用下划线或lodash https://lodash.com

// _.map : Produces a new array of values by mapping each value in list through a transformation function (iteratee)  http://underscorejs.org/#map 
_.map([1,2,3], function(value, index, collection){
  return _.without(collection, value)
}) // -> [[2,3],[1,3],[1,2]]

如果您喜欢这个lib,请检查is.js和string.js