如何获得更精细更精细的序列:1,16,8,4,12,......?

时间:2012-07-27 16:53:16

标签: algorithm recursion breadth-first-search

如果存在需要将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等数字来获得最终数组,它应该可以工作,但是有更好的解决方案吗?

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)