如何找到给定长度的两个最大不相交子数组?

时间:2019-05-24 10:20:11

标签: javascript arrays algorithm function sub-array

我需要编写一个函数,将正整数,正整数B和正整数C的数组A作为输入。 然后,该函数应返回长度为B和C的A的两个不相交子数组的元素的总和,这些元素的和为最大。例如,如果A = [3、11、1、2、9、4、5、6、1],B = 4和C = 2,则该函数应返回38。这是因为两个最大的不相交子数组长度为B和C的A为[9,4,5,6]和[3,11]。第一个子数组的元素之和为9 + 4 + 5 + 6 = 24,第二个子数组的元素之和为3 + 11 = 14,所以两个子数组的总和为38。

我编写了一个遍历A的函数,找到长度为B的A的所有子数组和长度为C的A的所有子数组,然后找到最大B长度的子数组的元素之和和最大的C长子数组的元素。起初我以为我可以将最大的C长子阵列和最大的B长子阵列相加得出38。但是后来我意识到我的函数不能确保B长子阵列和C长子阵列是不相交,而是仅找到长度分别为B和C的A的最大子数组,这是不够的。

它在上面的示例中有效,但是请考虑以下示例: A = [3,7,10,5,2,1,3,4],B = 4,C =2。在这里,仅找到最大的B长子阵列和最大的C长子阵列将产生[3, 7,10,5]和[7,10]。然后,该函数将继续求和3 + 7 + 10 + 5 = 25和7 + 10 = 17并返回38。但这并不可行,因为这两个子数组不是不相交的子数组。该函数应该返回[3,7,10,5]和[3,4]作为最大的B长和C长不交集子数组。然后,它应该对元素求和并得到32。换句话说,当长度为A且长度为B和C的最大子数组重叠时,函数应找到这样的B长度子数组和C长度子数组的组合,从而最大程度地增加要素。到目前为止,这是我的代码:

function solution(A, B, C) {
var groupB = [];
var sumgroupB;
var maxSumArrayB;
var valuesSumsBArray = [];
if (A.length < (B + C)) {
    return -1;
} else {
    for (var i = 0; i < A.length; i++) {
        if (i+B<=A.length) {
        groupB = A.slice(i, i+B);
        sumgroupB = groupB.reduce(function sum(a, b) { return a+b} );
        valuesSumsBArray.push(sumgroupB);
        }
    }
    maxSumArrayB = Math.max(...valuesSumsBArray);
}


var groupC = [];
var sumgroupC;
var maxSumArrayC;
var valuesSumsCArray = [];
if (A.length < (B + C)) {
    return -1;
} else {
    for (var i = 0; i < A.length; i++) {
        if (i+C<=A.length) {
        groupC = A.slice(i, i+C);
        sumgroupC = groupC.reduce(function sum(a, b) { return a+b} );
        valuesSumsCArray.push(sumgroupC);
        }
    }
    maxSumArrayC = Math.max(...valuesSumsCArray);
}

return [maxSumArrayB, maxSumArrayC];

}
console.log(solution([3, 11, 1, 2, 9, 4, 5, 6, 1], 4, 2)) 

如何解决该问题,以确保该函数不会汇总A的最大B长度和C长度子数组的元素,而是汇总最大的DISJOINT B长度和C的元素长子数组(使最终总和最大化的两个子数组)?

2 个答案:

答案 0 :(得分:0)

   function solution(A, B, C) {
     let max = -Infinity;

     for(let startB = 0; startB < A.length - B; startB++) {
       // C is before B
      for(let startC = 0; startC + C < startB; startC++) {
         const sum = [...A.slice(startC, startC + C), ...A.slice(startB, startB + B)].reduce((a, b) => a + b, 0);
         if(sum > max) max = sum;
      }
        // C is behind B
      for(let startC = startB + B; startC < A.length; startC++) {
         const sum = [...A.slice(startC, startC + C), ...A.slice(startB, startB + B)].reduce((a, b) => a + b, 0);
         if(sum > max) max = sum;
      }
    }

    return max;
  }

答案 1 :(得分:0)

您可以首先为每个子集的和获得一个数组,然后检查索引,并仅从不重叠的索引中获取和。

function getSums(array, size) {
    var sum = array.slice(0, --size).reduce((a, b) => a + b, 0);
    return array.slice(size).map((v, i) => sum += v - (array[i - 1] || 0));
}

function solution(array, ...sizes) {
    var sums = sizes.map(l => getSums(array, l)),
        i, j,
        max = 0;

    for (i = 0; i < sums[0].length; i++) {
        for (j = 0; j < sums[1].length; j++) {
            if (j >= i + sizes[0] || j + sizes[1] <= i) {
                max = Math.max(max, sums[0][i] + sums[1][j]);
            }
        }
    }
    return max;
}

console.log(solution([3, 11, 1, 2, 9, 4, 5, 6, 1], 4, 2));
console.log(solution([3, 7, 10, 5, 2, 1, 3, 4], 4, 2));