从间隔列表的子集中查找最小值和最大值

时间:2012-12-17 04:56:06

标签: algorithm

给出一个间隔列表(此处显示其索引):

0: 1,3
1: 0,4
2: 5,7
3: 6,9
4: 2,8

然后从列表索引中任意输入和输出,是否有一种很好的方法来确定包含相应间隔的最小值和最大值?

例如:0,4会给你0,92,3会给你5,9

我目前的解决方案是迭代范围内的每个间隔,将分钟保持在入点上,最大值保持在出点上。想知道是否存在算法技术的数据结构我忽略了当间隔列表很长时更快。由于间隔列表没有改变,也许我可以预先创建一些模型来表示不同的数据?

2 个答案:

答案 0 :(得分:2)

一种简单的方法是拥有树形结构。树的根将具有整个列表的最小/最大值。然后它会有两个孩子给出前半部分和后半部分的最小值/最大值等等。这将允许你有一个O(log(n))搜索算法,其中n是整个间隔列表的大小。

首先构建树。这可以通过将间隔列表分成两个并为每个子间隔创建一个树来递归地完成:

def makeTree(begin,end,intervals):
  if end==begin:
    return None
  if end==begin+1:
    return Node(begin,end,intervals[begin],None,None)
  partition=(begin+end)/2
  left=makeTree(begin,partition)
  right=makeTree(partition,end)
  range=combineRanges(rangeOf(left),rangeOf(right))
  return Node(begin,end,range,left,right)

获得树后,可以将树的根传递给此函数:

def findRange(node,begin,end):
  # If the node's range doesn't intersect the range you are looking for, 
  # then you don't have to look any deeper.
  if node is None or begin>=node.end or end<=node.begin:
    return None
  # If the node's range is completely inside the range you are looking for, then
  # you also don't need to look any deeper.
  if begin<=node.begin and end>=node.end:
    return node.range
  # Otherwise, check each child.
  left_range=findRange(node.left,begin,end)
  right_range=findRange(node.right,begin,end)
  # And return the combined result.
  return combineRanges(left_range,right_range)

请注意,我正在使用半开区间,例如,开始&lt; = x&lt;结束区间中的任何x。这只会使代码更清晰。

答案 1 :(得分:1)

可以很容易地看出,每个区间实际上都表示最小值和最大值。

所以问题变成了:给你2个数组,找到任何指定索引范围的最小值和最大值。

找到最小值和最大值是相似的,所以我们在这里讨论min。

首先,可以使用Segment tree轻松完成,就像@Vaughn Cato所说的那样。

实际上我们不需要使用像Segment tree这样强大的数据结构,还有另一种特定的算法来解决这个问题,称为Range Minimum Query

不过,我写了一篇关于RMQ的帖子,请参阅http://attiix.com/2011/08/22/4-ways-to-solve-%c2%b11-rmq/