找到总和最大的递增子序列
Posted
技术标签:
【中文标题】找到总和最大的递增子序列【英文标题】:Find the increasing subsequence with maximum sum 【发布时间】:2020-11-10 10:41:01 【问题描述】:我正在尝试查找数组的子数组(也:子序列)。到目前为止,我找到了正确的最大和,但不知道如何找到元素本身。 例如:
输入= [10,70,20,30,50,11,30] 输出 = [110, [10,20,30,50]]
我的代码找到了 110,但我很难找到元素。 我的代码:
const maxSubequence = (arr) =>
let i, j;
let msis = arr.slice(); //Copy input array
//result variables
let resultSeq = [];
let maxSum = 0;
let result = [];
/* Compute maximum sum values in bottom up manner */
for (i = 1; i < arr.length; i++)
for (j = 0; j < i; j++)
if (arr[i] > arr[j] && msis[i] < msis[j] + arr[i])
msis[i] = msis[j] + arr[i];
// console.log(tempSeq);
/* Pick maximum of all msis values */
let maxIndex = 0;
for (i = 0; i < msis.length; i++)
if (maxSum < msis[i])
maxSum = msis[i];
maxIndex = i;
//Retrieve the max sequence elements using msis max sums - NOT WORKING
var tempSeq = [msis[maxIndex]];
resultSeq = [arr[maxIndex]];
for (i = maxIndex - 1; i >= 0; i--)
if (msis[i] < tempSeq[0])
tempSeq.unshift(msis[i])
resultSeq.unshift(arr[i])
result = [maxSum, resultSeq];
return result;
console.log(
maxSubequence([10, 70, 20, 30, 50, 11, 30])
)
【问题讨论】:
你会分享一些输入和输出样本吗? arrayTwo = [30,20, 10,50];输出:[60,[10,50]] 一般需要维护maxSumStartIndex
和maxSumEndIndex
(或maxSumArrLength
)。
maxSumStartIndex 和 maxSumEndIndex(或 maxSumArrLength) - 已经尝试过类似的东西,但它不起作用
@חייםחדד 答案不应该是 [80, [30, 50] ] 吗?
【参考方案1】:
考虑将索引i
加入书签,其中先前的最大递增和序列结束于索引j
处的当前数字扩展。如果当前数字不扩展任何先前的序列,则将其设置为 -1。现在找到最大和的索引后,您可以使用书签返回,直到索引变为-1。反转的数组将是您预期的最大递增和序列。
const maxSubequence = (arr) =>
let i, j;
let msis = arr.slice(); //Copy input array
//result variables
let resultSeq = [];
let maxSum = 0;
let result = [];
var bookmark = new Array(arr.length);
bookmark[0] = -1;
/* Compute maximum sum values in bottom up manner */
for (i = 1; i < arr.length; i++)
bookmark[i] = -1;
for (j = 0; j < i; j++)
if (arr[i] > arr[j] && msis[i] < msis[j] + arr[i])
msis[i] = msis[j] + arr[i];
bookmark[i] = j;
// console.log(tempSeq);
/* Pick maximum of all msis values */
let maxIndex = 0;
for (i = 0; i < msis.length; i++)
if (maxSum < msis[i])
maxSum = msis[i];
maxIndex = i;
resultSeq = [arr[maxIndex]];
for (i = bookmark[maxIndex]; i >= 0; i = bookmark[i])
resultSeq.unshift(arr[i])
result = [maxSum, resultSeq];
return result;
console.log(
maxSubequence([30,20, 10,50])
)
【讨论】:
【参考方案2】: const findSum = arr =>
var sum = 0;
arr.forEach(element=>
sum = sum + element
);
return sum;
const maxSubequenceSum = arr =>
// L[i] - The Maximum Sum Increasing
// Subsequence that ends with arr[i]
var L = [];
for (var i = 0; i < arr.length; i++)
L[i] = [];
// L[0] is equal to arr[0]
L[0].push(arr[0]);
// Start from index 1
for (var i = 1; i < arr.length; i++)
// For each j less than i
for (var j = 0; j < i; j++)
/*
* L[i] = MaxSum(L[j]) + arr[i]
where j < i and arr[j] < arr[i]
*/
var sumLi = findSum(L[i]);
var sumLj = findSum(L[j]);
if ( (arr[i] > arr[j]) && (sumLi < sumLj) )
console.log(`$arr[i] > $arr[j] && $sumLi < $sumLj`);
L[j].forEach( k=>
if (!L[i].includes(k))
L[i].push(k);
console.log(L);
);
// L[i] ends with arr[i]
L[i].push(arr[i]);
// L[i] now stores Maximum Sum Increasing
// Subsequence of arr[0..i] that ends with arr[i]
// res = L[0];
var res = [L[0]];
// Find max
L.forEach( x =>
if (findSum(x) > findSum(res))
res = x;
);
// Results variables
var max = 0;
var subSequence=[];
var result;
//Summing res elements = Max sum
//Each res element = subsequence
res.forEach(i=>
max = max + i;
subSequence.push(i);
);
result = [max,subSequence];
//Time complexity: O(n^2))
return result;
【讨论】:
由于您的findsum
函数,您的解决方案是 O(n^3) 时间。我的答案中产生递增和序列的解决方案更好,因为它是 O(n^2) 时间。此外,它只需要 O(n) 额外空间,而您的解决方案需要 O(n^2) 额外空间。以上是关于找到总和最大的递增子序列的主要内容,如果未能解决你的问题,请参考以下文章