如果存在需要将delta添加到特定值的测试,则可以按以下顺序测试delta:1,2,3,... 15,16。
但是为了测试更细更精细的粒度,delta可以是这个序列:1,16,8,4,12 ......(也就是说,我们尝试1和16,这是两个极端情况,然后我们尝试8,这是一个中间数,然后是4,它是1和8的中间,然后是12,即8和16的中间。
如何在没有重复的情况下优雅地生成此序列?
现在我在Ruby 1.9.3中有这个:
$deltas = []
def getMidPoint(a, b)
return if (a - b).abs <= 1
midPoint = ((a + b) / 2).to_i
puts "a = #{a}, b = #{b}, midPoint = #{midPoint}"
$deltas << midPoint
getMidPoint(a, midPoint)
getMidPoint(midPoint, b)
end
$deltas << 1
$deltas << 16
getMidPoint(1, 16)
p $deltas
但结果是:
[1, 16, 8, 4, 2, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15]
我实际上可以在数字上添加“级别”(存储为元组):因此对于8,它是2级,对于12,它也是2级(级别是递归级别),然后最后,我可以收集级别1,然后是级别2等数字来获得最终数组,它应该可以工作,但是有更好的解决方案吗?
答案 0 :(得分:1)
你的算法存在的问题是它会越过整个&#34;左侧&#34;在进入&#34;右侧&#34;之前,因为getMidPoint(a, midPoint)
将在getMidPoint(midPoint, b)
执行之前导致许多递归。
一种可能的解决方案是使用队列。将调用排入队列而不是直接调用这两个函数,并始终调用队列中的第一个元素。
因此,在第一步中,您将输出8并且具有队列&lt; 1,8&gt;,&lt; 8,16&gt;并且你将调用&lt; 1,8&gt ;,输出4.接下来你将有&lt; 8,16&gt;&lt; 1,4&gt;&lt; 4,8&gt;你会打电话给&lt; 8,16&gt;并且输出12并且具有队列&lt; 1,4&gt;&lt; 4&gt;&lt; 8&gt;&lt; 8,12&gt;&lt; 12,16&gt;。等等。
我认为这更接近您的需求。
答案 1 :(得分:0)
如果项目数量不大(在我的实际情况下,它可以是16或最多300),也就是说,如果时间复杂度不是问题,那么它实际上可以通过越来越小的步进来完成粒度:
starting_value = 1
ending_value = 16
queue = [] << starting_value << ending_value
each_step = ((starting_value + ending_value) / 2).to_i
begin
starting_value.step(ending_value, each_step) {|i| queue << i if not queue.include? i}
each_step = (each_step / 2).to_i
end while each_step > 0
p queue
结果是:
[1, 16, 9, 5, 13, 3, 7, 11, 15, 2, 4, 6, 8, 10, 12, 14]
queue.include?
可以生成算法O(n * n * log n)
,但如果使用哈希表来检查该数字是否已添加,那么它似乎可以变为O(n log n)
。