【问题标题】:Is this right way to solve the array partition problem?这是解决阵列分区问题的正确方法吗?
【发布时间】:2020-02-24 01:28:30
【问题描述】:

leetcode.com 向我提出了问题

问题陈述:

给定一个由 2n 个整数组成的数组,您的任务是将这些整数分组为 n 对整数,例如 (a1, b1), (a2, b2), ..., (an, bn),它们的总和为 min (ai, bi) 对从 1 到 n 的所有 i 尽可能大。

示例 1: 输入:[1,4,3,2]

输出:4
解释:n为2,对的最大和为4 = min(1, 2) + min(3, 4)。

注意: n 为正整数,取值范围为 [1, 10000]。 数组中的所有整数都将在 [-10000, 10000] 的范围内。

我已尝试使用以下 javascript 代码解决此问题

// NOTE: This is more optimal and can work
function chunkWithoutIndex(inputArr, partition) {
  let length = inputArr.length;
  let sliced = [];
  let count = 0;
  for (let i = 0; i <= length - 1; i++) {
    let subArr = sliced[count];
    if (!subArr) {
      sliced[count] = [];
    }
    let subArrLen = sliced[count].length;
    if (subArrLen !== partition) {
      sliced[count].push(inputArr[i]);
    } else {
      count++;
      sliced[count] = [inputArr[i]]
    }
  }
  return sliced;
}

// NOTE: This does not consider the chunk size
function checkWithTwoPointers(inputArr) {
  let length = inputArr.length;
  let left = 0;
  let right = length - 1;
  let sliced = [];
  while (left <= right) {
    if (left !== right) {
      sliced.push([inputArr[left], inputArr[right]]);
    } else {
      sliced.push([inputArr[left] || inputArr[right]]);
    }
    left++;
    right--;
  }
  return sliced;
}

function arrayPartition(inputArr, partition) {
  // let sliced = chunkWithoutIndex(inputArr, partition);
  let sliced = checkWithTwoPointers(inputArr);
  let sum = 0;
  let slicedLen = sliced.length;
  for (let i = 0; i <= slicedLen - 1; i++) {
    sum = sum + Math.min(...sliced[i]);
  }
  return sum;
}

在提交问题以供接受时,由于不同的测试用例而失败。

看到输入 = [1, 4, 3, 2] 的测试用例运行良好,它期望输出为 4。 所以配对是

(1, 4) , (3, 2) = 1 + 2 = 3
(1, 3), (4, 2) = 1 + 2 = 3
(1, 2), (4, 3) = 1 + 3 = 4 --> Selected Pair

还有一个测试用例 input = [1, 1, 2, 2] ,它期望输出是 3?

如果我使用上面编写的相同函数,它将创建一对 (1,2) , (1, 2) => 1+ 1 = 2。但他们现在期待这对 (1,1), ( 2, 2) => 1 + 2 = 3。

如何解决这个问题?我在这里错过了什么吗?

【问题讨论】:

    标签: javascript python arrays algorithm


    【解决方案1】:

    数字越接近,取最小值时丢失的越少。对数组进行排序,然后分块,并对最小值求和(每个子数组的第一项)。

    const chunk = (size, arr) => Array.from(
      { length: Math.ceil(arr.length / size) }, 
      (_, i) => arr.slice(size * i, size * (i + 1))
    )
    
    const sumMin = (size, arr) =>
      chunk(size, [...arr].sort())
      .reduce((s, [n]) => s + n, 0)
      
    console.log(sumMin(2, [1, 2, 3, 4]));
    console.log(sumMin(2, [1, 2, 1, 2]));

    【讨论】:

    • 感谢您的回答,我真的学到了 Array.from 使用 length 属性的方法。
    【解决方案2】:

    当你取两个数字中的最小值时,对我们来说更大的数字就变得无关紧要了,所以我们的目标是确保每一对都尽可能接近,这可以通过sorting 来实现,并且只在其中添加元素均匀的位置。

    let arrSum = (arr) => arr.sort().filter((d, i) => i % 2 == 0).reduce((a, b) => a + b)
    
    
    console.log(arrSum([1, 2, 3, 4]))
    console.log(arrSum([1, 1, 2, 2]))

    【讨论】:

      【解决方案3】:

      诀窍是先对数组进行排序,然后对每个具有偶数索引的数字求和(即每对中最小的数字)。

      var arrayPairSum = function(nums) {
          nums.sort((a, b) => a - b);
          let sum = 0;  
      
          for(let i = 0; i < nums.length; i += 2) {
              sum += nums[i];
          }
      
          return sum;
      };
      

      在 LeetCode 上测试:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-23
        • 2023-03-14
        • 1970-01-01
        • 2020-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多