具有近似值且无重复的数字之和

时间:2015-11-17 20:58:04

标签: algorithm language-agnostic heuristics

对于我正在处理的应用程序,我需要处理一个数字数组并返回一个新数组,使得元素之和尽可能接近目标总和。这类似于coin-counting problem,有两点不同:

  1. 新数组的每个元素必须来自输入数组(即没有重复/重复)
  2. 算法应该在找到一个总和落在目标数X的范围内的数组时停止(例如,给定[10,12,15,23,26],目标为35,sigma为5,结果[10,12,15](总和37)是可以的,但[15,26](总和41)的结果不是。
  3. 我正在考虑以下算法(伪代码),但我怀疑这是最好的方法。

    function (array, goal, sigma)
        var A = []
        for each element E in array
            if (E + (sum of rest of A) < goal +/- sigma)
                A.push(E)
        return A
    

    对于它的价值,我使用的语言是Javascript。任何建议都非常感谢!

4 个答案:

答案 0 :(得分:0)

这不是最好的答案,只是可能会运作得很好。欢迎所有评论/意见 此外,这是考虑到评论的答案,输入是歌曲的长度(通常为100 - 600),输入数组的长度在5到50之间,目标在100到7200之间。

想法:

  1. 首先找到输入的平均值,然后猜测您将需要的输入值的数量。让我们说出来x
  2. 订购您的输入。
  3. 取第一个x-1值并用最小的值替换任何其他值以达到目标(范围内的某个位置)。如果不存在,请找到一个数字,以便您仍然低于目标。
  4. 使用回溯或类似的方式重复步骤#3。也许会限制你将在那里度过的试验次数。
  5. x++然后返回第3步。

答案 1 :(得分:0)

我会使用某种分而治之和递归实现。这是Smalltalk的原型

SequenceableCollection>>subsetOfSum: s plusOrMinus: d
    "check if a singleton matches"
    self do: [:v | (v between: s - d and: s + d) ifTrue: [^{v}]].

    "nope, engage recursion with a smaller collection"
    self keysAndValuesDo: [:i :v |
        | sub |
        sub := (self copyWithoutIndex: i) subsetOfSum: s-v plusOrMinus: d.
        sub isNil ifFalse: [^sub copyWith: v]].

    "none found"
    ^nil

像这样使用:

#(10 12 15 23 26) subsetOfSum: 62 plusOrMinus: 3.

给出:

#(23 15 12 10)

答案 2 :(得分:0)

以下是JavaScript中的一个评论算法:

global $wpdb;
$customers = $wpdb->get_results("SELECT name, phone FROM customers;");

foreach($customers as $c){
echo "<option value='name'>".$c->name."</option>";
}
echo "</select>";
echo "<select>";
foreach($customers as $c){
echo "<option value='name'>".$c->name."</option>";
}
echo "</select>";

答案 3 :(得分:0)

如果输入有限,这个问题是时间复杂度O((Sum + Sigma) * ArrayLength)

的动态编程的理想选择

德尔福代码:

  function FindCombination(const A: array of Integer; Sum, Sigma: Integer): string;
  var
    Sums: array of Integer;
    Value, idx: Integer;
  begin
    Result := '';
    SetLength(Sums, Sum + Sigma + 1); //zero-initialized array
    Sums[0] := 1; //just non-zero

    for Value in A do begin
      idx := Sum + Sigma;
      while idx >= Value do begin
        if Sums[idx - Value] <> 0 then begin //(idx-Value) sum can be formed from array]

          Sums[idx] := Value;    //value is included in this sum

          if idx >= Sum - Sigma then begin  //bingo!
            while idx > 0 do begin  //unwind and extract all values for this sum
              Result := Result + IntToStr(Sums[idx]) + ' ';
              idx := idx - Sums[idx];
            end;
            Exit;
          end;

        end;
        Dec(idx); //idx--
      end;
    end;
  end;