【问题标题】:Split array into arrays of numbers where the sum is equal to a specific target将数组拆分为总和等于特定目标的数字数组
【发布时间】:2021-01-25 08:27:32
【问题描述】:

我需要创建一个以数组和目标为参数的函数。它应该返回一个数组数组,其中这些数字的总和等于目标

sumPairs(array, target) {

}

例如:

sumPairs([1, 2, 3, 4, 5], 7) // output : [[2, 5], [3, 4]]

我知道我必须使用 map(),可能还有 reduce()set()filter()(我在 MDN 中阅读了他们的文档,但仍然无法找到)。我尝试了一些方法,但我无法得到它。

如果你们能帮助我了解如何动态创建数组并将它们推入新数组..

我在那里阅读了一些解决方案 (Split array into arrays of matching values),但我讨厌在不知道它们真正做什么或如何工作的情况下使用创建的函数。

【问题讨论】:

  • 我的意思是,我不知道需要多少个数组才能推入 newArray,如果您有任何解决方案,reduce() 可能会有所帮助(以及解释,因为如果没有我不会学习从解决方案)
  • 子数组只能有 2 个项目,或者如果数组,您必须产生最小/最大数量?
  • 练习说它应该是对目标值求和的数组,所以我认为只有 2 个项目
  • 您可以在线性时间内实现这一点,而不是像所选答案那样在二次时间内实现。

标签: javascript arrays


【解决方案1】:

实现它的一些非常基本的代码,只需运行所有组合并有条件地添加您想要的项目。

function sumPairs(array, target) {
  var res = [];
  for(var i = 0; i < array.length; i++){
    for(var j = 0; j < array.length; j++){
      if(i!=j && array[i]+array[j]==target && 
      res.filter((x)=> x[0] == array[j] && x[1] == array[i]).length == 0 )
        res.push([array[i], array[j]]);
    }
  }
  return res;
}

var result = sumPairs([1, 2, 3, 4, 5], 7);
console.log(result);

选项 2 - 请参阅 answer 了解更多选项(例如使用 reduce)

function sumPairs(array, target) {
  return array.flatMap(
    (v, i) => array.slice(i+1).filter(w => (v!=w && v+w==target)).map(w=> [w,v])
  );
}

var result = sumPairs([1, 2, 3, 4, 5], 7);
console.log(result);

【讨论】:

  • 谢谢你千千万万次!需要练习我的思维逻辑!!
  • 我很难理解选项 1,i & j 在某个时间点会有什么不同?
  • 你能解释一下第一个选项的作用吗?
  • 至少只是你在第一个选项中使用的条件 lol
  • 否,例如:在第一次迭代中,array[0] === array[0]...
【解决方案2】:

您还可以使用两个指针方法对数组进行排序并找到所有具有给定总和的对。将第一个指针指向数组的开头,将第二个指针指向数组的末尾。

如果两个地方的值之和是:

  1. 超过目标:将第二个指针减 1
  2. 小于目标:将第一个指针增加 1
  3. 等于目标:这是一个可能的答案,将它们推送到您的答案数组,并将您的第一个指针加 1,将第二个指针减 1。

这是更高效的解决方案,复杂度为 O(n*log(n))

【讨论】:

  • 你甚至可以做线性复杂度;)
【解决方案3】:

“这个练习说它应该是对数组求和 目标值,所以我认为只有 2 项”

如果您需要一对匹配总和的数字,并且从列表中选择任意数字,则剩下 下面的方程来解决我们想要找到xnum + x = sum。例如。如果您选择了7 并且目标总和是10,那么您知道您正在寻找3

因此,我们可以首先构建列表线性 (O(n)) 时间中可用数字的计数图,然后在线性时间中搜索匹配项,而不是使用二次算法进行暴力破解。

const nums = [1, 2, 3, 4, 5];

console.log(findSumPairs(nums, 7));

function findSumPairs(nums, sum) {
  const countByNum = countGroupByNum(nums);
  
  return nums.reduce((pairs, num) => {
    countByNum[num]--; 
    const target = sum - num;
    
    if (countByNum[target] > 0) {
      countByNum[target]--;
      pairs.push([num, target]);
    } else {
      countByNum[num]++;
    }
    
    return pairs;
  }, []);
}

function countGroupByNum(nums) {
  return nums.reduce((acc, n) => (acc[n] = (acc[n] || 0) + 1, acc), {});
}

这是另一个具有更多标准范例的实现(例如,没有 reduce):

const nums = [1, 2, 3, 4, 5];

console.log(findSumPairs(nums, 7));

function findSumPairs(nums, sum) {
  const countByNum = countGroupByNum(nums);
  const pairs = [];

  for (const num of nums) {
    const target = sum - num; //Calculate the target to make the sum
    countByNum[num]--; //Make sure we dont pick the same num instance

    if (countByNum[target] > 0) { //If we found the target
       countByNum[target]--;
       pairs.push([num, target]);
    } else {
       countByNum[target]++; //Didin't find a match, return the deducted num
    }
  }

  return pairs;
}

function countGroupByNum(nums) {
  const countByNum = {};

  for (const num of nums) {
    countByNum[num] = (countByNum[num] || 0) + 1;
  }

  return countByNum;
}

【讨论】:

  • (顺便说一句,你的答案比之前标记的答案更能帮助我,只是改变了)
  • 我将重写第二个实现而不使用reduce。
  • 第二次实现超级帮助我理解了推理!现在我将尝试使用 reduce() 方法来理解。非常感谢您的帮助!
  • 当总和应该为 0 并且有如下列表时遇到问题:[6, -6, 8, -8, 1, 9, -10, 0, 0]我得到 [ [ 6, -6 ], [ 8, -8 ], [ 0, 0 ], [ 0, 0 ] ] 而不是 [ [ 6, -6 ], [ 8, -8 ], [ 0, 0 ]]
  • 好的,我刚刚在 if (countByNum[target] 也应该 > 0) 中添加了一个条件
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 2020-09-14
  • 1970-01-01
  • 2020-09-13
  • 1970-01-01
相关资源
最近更新 更多