【问题标题】:Finding a good match of two lists of numbers找到两个数字列表的良好匹配
【发布时间】:2013-01-08 03:57:22
【问题描述】:

我有两组数字,其中 SET2 通常包含更多项目。保证 SET2 的计数等于或大于 SET1 的计数。 实际上,由于顺序很重要,因此输入是列表而不是集合。

我的目标是组合(总结)/重新排序 SET2 中的数字,使其尽可能类似于 SET1。我将相似度定义为每个位置的偏差之和。请参阅this post 了解我计算相似度的方式。总和越小越好。

我的第一个方法是尝试所有组合并选择最佳组合。这仅适用于相当小的集合(尤其是第二个)。请参阅this post 和 Rawling 的回答。 有没有更聪明的方法来获得良好的组合?我绝对不需要最好的。一个好的结果会很好。显然,具有空子集的集合是无稽之谈。极端不平衡的集合对我来说似乎不是很有希望。 SET1 往往有大约 8 个,但最多可以有 18 个条目。 SET2 的计数通常超过 10(最多 35)。 两组数字之和相等(舍入误差除外)。

这是一个有好有坏结果的示例(并非所有可能的结果):

SET1 = { 272370, 194560, 233430 }; SET2 = { 53407.13, 100000, 365634.03, 181319.07 }

      272370            |      194560          |        233430 
---------------------------------------------------------------------
     365634.03         |  100000 + 53407.13   |      181319.07       (best match)
     365634.03         |     181319.07        |  100000 + 53407.13   (good)
     365634.03         |      100000          |181319.07 + 53407.13  (ok)
      53407.13          |365634.03 + 100000    |      181319.07       (bad)
      53407.13          |365634.03 + 181319.07 |        100000        (bad)
.                 |365634.03 + 181319.07 | 53407.13 + 100000    (invalid)
53407.13 + 100000 |365634.03 + 181319.07 |                      (invalid)

如果我忘记描述前提或者我的描述不清楚甚至有错误,请告诉我。我也很乐意提供另一个例子。

提前致谢!

【问题讨论】:

  • 您是在寻找最佳答案还是快速启发式?
  • 快速启发式算法将是完美的。特别是因为不可能进行详尽的计算。感谢@Ari 的评论。

标签: c# algorithm


【解决方案1】:

启发式,应该很好用:

1. list<int> set1, set2;
2. sort(set2) // decreasing, set2[0] would be the greatest value in set2
3. struct set1item = {set1index, value, list<int> chosen}
4. prepare list<set1item> set1items from set1 //(index = index in set1 list, value = set1[index] and chosen = null)
5. put set1items to some priorityqueue pq // ordered by value
6. for each set2item in set2{
7.     item = pq.first()
8.     item.chosen.add(set2item);
9.     item.value -= set2item;
10.    pq.updateFirst(item)
11.}

它的工作原理是:从最高到最低遍历 set2,从 set1 中获取实际最高元素,通过从 set2 中获得的元素减少它,然后将 set2 中的这个元素添加到 set1 结果中的元素。

你必须记得检查 set1 中的所有元素是否都没有空结果。

示例 1: Set1 = {20, 9, 7, 3}, Set2 = {7, 6, 6, 4, 2, 2, 2, 2, 2, 2, 2, 2}.

iter1:fromSet2 = 7Set1 = {20:{}, 9:{}, 7:{}, 3:{}}fromSet1=20。 将 20 减 7 并将结果加 7。更新:Set1 = {13:{7}, 9:{}, 7:{}, 3:{}}

iter2:fromSet2 = 6Set1 = {13:{7}, 9:{}, 7:{}, 3:{}}fromSet1=13。 将 13 减 6 并将结果加 6。更新:Set1 = {7:{7, 6}, 9:{}, 7:{}, 3:{}}

iter3:fromSet2 = 6Set1 = {7:{7, 6}, 9:{}, 7:{}, 3:{}}fromSet1=9。 将 9 减 6 并将结果加 6。更新:Set1 = {7:{7, 6}, 3:{6}, 7:{}, 3:{}}

iter4:fromSet2 = 4Set1 = {7:{7, 6}, 3:{6}, 7:{}, 3:{}}fromSet1=7。 将 7 减 4 并将结果加 4。更新:Set1 = {3:{7, 6, 4}, 3:{6}, 7:{}, 3:{}}

iter5:fromSet2 = 2Set1 = {3:{7, 6, 4}, 3:{6}, 7:{}, 3:{}}fromSet1=7。 将 7 减 2 并将结果加 2。更新:Set1 = {3:{7, 6, 4}, 3:{6}, 5:{2}, 3:{}}

...

【讨论】:

  • 所以...总是将最大的空闲盒子放入剩余空间最多的垃圾箱中?
  • 您的解决方案解释清楚且易于实施@Ari。对于另一个测试用例,它工作得很好。我会进一步评估并提供反馈。
  • 这个算法效果很好。实际上,垃圾箱空着的情况经常发生。感谢您明确提到这可能会发生。如果 set2 中剩下的元素多于空结果,我只选择 set1 中的最大值来防止这种情况。如果不是这种情况,我会选择空集的最大值。
猜你喜欢
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-07
  • 2015-05-23
  • 1970-01-01
  • 2017-05-01
  • 1970-01-01
相关资源
最近更新 更多