在数组中查找具有最小差异和连续元素的 2 个子集
Posted
技术标签:
【中文标题】在数组中查找具有最小差异和连续元素的 2 个子集【英文标题】:Find 2 subsets in array that have minimum difference and consecutive elements 【发布时间】:2018-02-26 23:09:10 【问题描述】:我遇到了一个我觉得很有趣的子集和问题的变体。因此,给定一个(正)元素数组,您必须将其划分为 2 组,以使它们的差异最小。但这就是问题所在。元素必须是连续的,并且它们也以循环顺序工作。这里有 2 个例子,你可以理解我的意思:
示例 1:
输入:7 5 1 3 8 9 11 8
输出:0(设置 1:11,8,7,设置 2:5,1,3,8,9
.
示例 2:
输入:10 14 75 90 3 5 40 4 8
输出:27(第 1 组:4,8,10,14,75,第 2 组:90,3,5,40)
使用 C++ 的可能解决方案是什么?谢谢!
【问题讨论】:
【参考方案1】:有线性时间解决方案使用两指针方法。目标参数是范围,其总和尽可能接近其余参数的总和。
将两个索引left, right
设置为数组开头。 csum
是数组范围 left..right-1
的当前总和。
如果再添加一个元素会使当前 cum 更接近理想值,则向右移动索引并更新参数。
当添加元素使当前总和变差时,开始删除左侧元素。
Delphi 代码仅返回最佳差异,范围本身((left,right-1)
对)可能在自己的 Min
操作实现中找到。
function Nice(A: TArray<Integer>): Integer;
var
left, right, i, sum, csum, diff: Integer;
begin
sum := 0;
for i := 0 to High(A) do
sum := sum + A[i];
left := 0;
right := 1;
csum := A[0]; //sum of current subsequence
diff := Abs(sum - 2 * csum); //dif = Abs((sum - csum) - csum)
result := diff;
repeat
//if adding right element makes difference better
while (right < Length(A)) and (Abs(sum - 2 * (csum + A[right])) < diff) do begin
csum := csum + A[right];
diff := Abs(sum - 2 * csum);
result := Min(result, diff);
right := right + 1;
end;
repeat
csum := csum - A[left]; //we always need at least one step
diff := Abs(sum - 2 * csum);
result := Min(result, diff);
left := left + 1;
until (left = right) or (Abs(sum - 2 * (csum - A[left])) >= diff);
until (left = right);
end;
【讨论】:
感谢您的宝贵时间!如果我们使用动态编程方法而不是直接的解决方案,这会更有效吗? 这种方法效率最高。它可能被视为一种 DP - 想象在左/右表中填充一些轨迹 好吧,我遇到了一个错误,程序返回 14 作为第二组的最佳差值,但答案是 27。有什么想法吗? @dituoa 函数找到优化参数 14 作为 halfsum 124 和 90..40 子序列和 138 的差。其余的有 sum 111,所以 138-111=27。我会写更正以返回您需要的值以上是关于在数组中查找具有最小差异和连续元素的 2 个子集的主要内容,如果未能解决你的问题,请参考以下文章
ArrayIndexOutOfBoundsException,同时找到数组中两个连续元素之间的最大差异