【问题标题】:Find 2 subsets in array that have minimum difference and consecutive elements在数组中查找具有最小差异和连续元素的 2 个子集
【发布时间】: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++ 的可能解决方案是什么?谢谢!

【问题讨论】:

    标签: c++ algorithm c++11 knapsack-problem subset-sum


    【解决方案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。我会写更正以返回您需要的值
    猜你喜欢
    • 1970-01-01
    • 2015-11-09
    • 2021-04-25
    • 1970-01-01
    • 2017-01-17
    • 2015-07-27
    • 1970-01-01
    • 2015-11-08
    • 2016-11-17
    相关资源
    最近更新 更多