【问题标题】:Array of numbers to batches of given sum给定总和批次的数字数组
【发布时间】:2020-05-14 10:14:14
【问题描述】:

我有一个 JavaScript 数组并作为输入求和

array = [4,8,2,4,2,2,8,12,4,2, 2]
sum = 12 // all the time sum will be 12

我要二维数组,分批的数字应该是总和等于或小于12

输出数组应该是这样的

[
  [4,8],
  [2,4,2,2,2],
  [8, 4],
  [12],
  [2]
]

4 + 8 = 12
2 + 4 + 2 + 2 + 2 = 12
...
2 is left at the end

其他例子

1) 数组 = [6,5,3,3,3,2,2,2,2] 总和 = 12

输出:[[6,3,3],[5,3,2,2],[2,2]]

一个数字分配给子集,它不应该用于其他子集

余数可以加到最后,但总和小于12,否则再加一个数组,余数相加

输入数组可以是 1 - 12 之间的任何整数

我怎样才能得到我想要的输出?

【问题讨论】:

  • 如果[7, 7, 7, 7, 7],您永远无法将数组的总和设为 12。这里可以是[ [7], [7], [7], [7] ]。你想如何处理这个问题?还是最大和为 12?
  • @Soham,如果是这种情况,那么输出将是 [ [7], [7], [7], [7], [7] ]
  • 你对[4,4,4,8]的结果有什么期望?
  • 所以,只是为了确保我理解:您更喜欢对而不是所有其他类型的分组。
  • 没有顺序无所谓

标签: javascript arrays loops for-loop


【解决方案1】:

试试这个功能。我尽可能对代码进行注释以澄清它。

const example1 = [4, 8, 2, 4, 2, 2, 8, 12, 4, 2, 2];
const example2 = [6, 5, 3, 3, 3, 2, 2, 2, 2];
const example3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const example4 = [5,12,3,4,4,1,1,1,5,8,12,6,9,11,6];
const example5 = [4, 2, 1, 2, 3, 3, 5, 7, 8, 9];

const lookAhead = function(array, searchFor) {
  return array.some(val => {
    return val <= searchFor;
  });
}

function findPairs(inputArray) {

  // First sort array in descending order
  inputArray.sort((a, b) => b - a);
  console.log("input", JSON.stringify(inputArray.slice(0)));

  // set variables
  const pairArray = [];
  const max = 12;

  inputArray.forEach(function(num, index) {
    // when looping the array we will replace values with null once completed,
    // Therefore if value is null no need to go futher
    if (num == null)
      return;

    // initiate pair value with current number
    const pair = [num];

    // set it to null in input array
    inputArray[index] = null;

    // if number equals to max (ie. 12) no need to go futher
    if (num == max) {
      pairArray.push(pair);
      return;
    }

    let total = num;

    // Loop through array again to see matching numbers
    for (let i = 0; i < inputArray.length; i++) {

      // Don't go futher if it is a null value
      if (inputArray[i] == null)
        continue;

      const add = total + inputArray[i];

      /* if the total is less than max (12) then we check if we have an edge case
       * For example in an array like [6, 5, 3, 3, 3], 6 + 5 is 11 but in next loops we  
       * will not find any "1" to get to 12. Therefore we escape this iteration and check
       * next numbers. In this case the result would be 6 + 3 + 3
       */
      if (add < max) {
        const found = lookAhead(inputArray.slice(i), max - add);
        if (found) {
          pair.push(inputArray[i]);
          total = add;
          inputArray[i] = null;
        }
      } else if (add == max) {
        // The addition is equals to max. Push the number and set it to null in input array
        pair.push(inputArray[i]);
        inputArray[i] = null;
        total = 0;
        break;
      }
    }

    // Push pair array from this iteration to  pairArray
    pairArray.push(pair);
  });

  console.log("output", JSON.stringify(pairArray));
  console.log("-------");
}

findPairs(example1);
findPairs(example2);
findPairs(example3);
findPairs(example4);
findPairs(example5);

【讨论】:

  • 感谢您在这里帮助我。您的解决方案适用于所有用例。你是一个 javascript 传奇
【解决方案2】:

理解起来有点复杂,但你去吧......

let originalArray = [7, 7, 7, 7, 7]
let sum = 12;
let twoDiArray = [];

let CalculateSum = (array, element) => {
  array = [...array, element]
  return array.reduce((x, y) => {
    return x + y;
  })
}

twoDiArray.push([]);

originalArray.forEach(element => {
  for (let i = 0; i < twoDiArray.length; i++) {
    if (CalculateSum(twoDiArray[i], element) <= 12) {
      twoDiArray[i].push(element);
      break;
    } else {
      if (twoDiArray.length - 1 === i) {
        twoDiArray.push([element]);
        break;
      }
    }
  }
})

console.log(twoDiArray)

【讨论】:

  • 感谢您的努力,它按给定的顺序工作,但是当输入为 [1,2,3,4,5,6,7,8,9,10,11,12] ,输出为[[1,2,3,4],[5,6],[7],[8],[9],[10],[11],[12]]。期望是 [ [1, 11], [2, 10], [3, 9], [4, 8], [5,7]。 [12],[6]]。是否有可能得到这个输出@soham?
  • 我们需要所有可能的批次总和 12 对
【解决方案3】:

给你...我将保留两个答案以供其他人将来使用...

let originalArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
let sum = 12;
let twoDiArray = [];

let CalculateSum = (array, element) => {
  array = [...array, element]
  return array.reduce((x, y) => {
    return x + y;
  })
}

twoDiArray.push([originalArray[0]]);
originalArray.splice(0, 1);

do {
  originalArray.forEach((element, index) => {
    for (let i = 0; i < twoDiArray.length; i++) {
      let summ = CalculateSum(twoDiArray[i], element);
      if (summ === 12) {
        twoDiArray[i].push(element);
        originalArray.splice(index, 1);
        break;
      } else {
        if (index === originalArray.length - 1) {
          if (CalculateSum(twoDiArray[twoDiArray.length - 1], originalArray[0]) <= 12) {

            twoDiArray[twoDiArray.length - 1].push(originalArray[0]);

            break;
          } else {
            twoDiArray.push([originalArray[0]]);
          }
          originalArray.splice(0, 1);
        }

      }
    }
  })
}
while (originalArray.length > 0);

console.log(twoDiArray)

【讨论】:

  • 对于[6,5,3,3,3,2,2,2,2] 的输入,该算法的输出不正确。它在应该输出 [[6,3,3], [5,3,2,2], [2,2]] 时输出 [[6, 5],[5, 3, 3],[3, 3, 3, 3],[3, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2],[2]]
  • @soham,上面的这个逻辑在子集中给出了重复的值,你能不能给上面的代码添加一个修复
猜你喜欢
  • 2020-11-25
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
相关资源
最近更新 更多