将一组数字拆分为尽可能最少的定义“间隔长度”算法的子集

时间:2013-10-30 11:07:14

标签: algorithm math modbus

考虑我有一些数字。例如{1,2,3,7,8,9,11,15,16}。我需要的是将该组分成尽可能少的子集,并且最低和最高数之间的差异小于9。 从我的例子中,它将是例如:
{1,2,3,7,8},{9,11,15,16}
我需要这个来优化通过Modbus的“读取多个寄存器”请求的数量 我已经尝试将集合拆分为具有连续数字的子集而不是将它们合并,但它并不理想,因为它会将此返回给我:
{1,2,3},{7,8,9,11},{15,16}或{1,2,3},{7,8,9},{11,15,16} 正如你所看到的,这种方法给了我三个子集而不是两个子集 有没有可用的算法?
感谢

1 个答案:

答案 0 :(得分:3)

贪婪的方法怎么样,即将元素从左边插入到集合中,当你超越所需的差异时,创建一个新的集合。

因此,1, 2, 3, 7, 8, 9, 11, 15, 16

你从1.开始 2-1 = 1< 9,所以加2.
3-1 = 2< 9,所以加3. 7-1 = 6< 9,所以加7. 8-1 = 7< 8-1 9,所以加8 9-1 = 8< 9,所以加9. 11-1 = 10> 9,所以创建一个新的集 15-11 = 4< 9,所以加15 16-11 = 5< 9,所以加16。

输出:{1, 2, 3, 7, 8, 9}, {11, 15, 16}

注意:

如果元素不必排序,我们可以先对它们进行排序。

如果这些子集不必连续,则不会产生差异,因为从有序输入中选择连续集始终优于非连续集。

如果元素不必排序,则子集必须是连续的,这会稍微改变问题。

最佳性证明:

设S是该算法为某些任意输入产生的集合赋值。

进行任何设定作业T。

令S i 为第i组S.
令T i 为第i组T。

设S i-size 是第i组S的大小。
令T i-size 为第i组T的大小。

假设S和T不同,则对于某些S i 和T i ,S i-size != T I-大小。具体来说,选择第一组i,其中两者不同。

所以S i-size &gt; T i-size 或S i-size &lt; Ť<子> I-大小

j&gt;我是不可能的,因为这个算法从一开始就采用尽可能多的元素。

如果j < i,S i + 1 的第一个元素将大于T i + 1 的第一个元素,并且由于算法是贪婪的,S i + 1 至少包括S i 中尚未包含的T i + 1 的所有元素。

现在,由于上述原因,S i + 2 的第一个元素同样会大于T i + 2 的第一个元素,因此S i + 2 将至少包括先前S组中尚未包括的T i + 2 的所有元素。类似地,对于S和T的其余组,因此存在在T中至少与S中的数量一样多。

因此,该算法产生的设定分配不会比任何其他分配更差。因此它是最佳的。