Algorithm 从区间列表的子集中查找最小值和最大值
给出一个间隔列表(此处显示了它们的索引): 然后给定列表索引的任意输入和输出,是否有一种好方法可以从包含的相应间隔中确定最小值和最大值 例如:Algorithm 从区间列表的子集中查找最小值和最大值,algorithm,Algorithm,给出一个间隔列表(此处显示了它们的索引): 然后给定列表索引的任意输入和输出,是否有一种好方法可以从包含的相应间隔中确定最小值和最大值 例如:0,4将为您提供0,92,3将为您提供5,9 我目前的解决方案是迭代范围内的每个间隔,在输入点上保持min,在输出点上保持max。我想知道是否有一个算法技术的数据结构,我忽略了它,以便在间隔列表很长的情况下加快速度。由于间隔列表没有改变,也许我可以预先创建一些模型来以不同的方式表示数据?一个简单的方法是使用树结构。树的根将具有整个列表的最小/最大值。然后它
0,4
将为您提供0,9
<代码>2,3将为您提供5,9
我目前的解决方案是迭代范围内的每个间隔,在输入点上保持min,在输出点上保持max。我想知道是否有一个算法技术的数据结构,我忽略了它,以便在间隔列表很长的情况下加快速度。由于间隔列表没有改变,也许我可以预先创建一些模型来以不同的方式表示数据?一个简单的方法是使用树结构。树的根将具有整个列表的最小/最大值。然后它将有两个子项,它们给出上半部分和下半部分的最小/最大值,等等。这将允许您使用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)
def findRange(节点、开始、结束):
#如果节点的范围与要查找的范围不相交,
#那你就不必再看得更深了。
如果node为None或begin>=node.end或end,一种简单的方法是使用树结构。树的根将具有整个列表的最小/最大值。然后它将有两个子项,它们给出上半部分和下半部分的最小/最大值,等等。这将允许您使用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)
def findRange(节点、开始、结束):
#如果节点的范围与要查找的范围不相交,
#那你就不必再看得更深了。
如果node为None或begin>=node.end或end,很容易看出,每个间隔实际上表示一个最小值和一个最大值 所以问题变成了:给你2个数组,找到任何指定索引范围的最小值和最大值 求最小值和最大值是相似的,所以我们在这里讨论最小值 首先,正如
@Vaughn Cato
所说的,它可以很容易地完成
实际上,我们不需要使用像段树
这样功能强大的数据结构,有另一种特定的算法来解决这个问题,叫做
顺便说一句,我写了一篇关于
RMQ
的帖子,请参阅。,因为很容易看出,每个间隔实际上表示一个最小值和一个最大值
所以问题变成了:给你2个数组,找到任何指定索引范围的最小值和最大值
求最小值和最大值是相似的,所以我们在这里讨论最小值
首先,正如@Vaughn Cato
所说的,它可以很容易地完成
实际上,我们不需要使用像段树
这样功能强大的数据结构,有另一种特定的算法来解决这个问题,叫做
顺便说一句,我写了一篇关于
RMQ
的帖子,请参阅。一个简单的方法是建立一个树结构。树的根将具有整个列表的最小/最大值。然后,它将有两个孩子,分别给出上半部分和下半部分的最小值/最大值,等等。这将允许您对任何子范围使用log(n)算法。如果您能负担得起O(n²)
空间,则有一个明显的O(1)
时间算法:只需记录所有minmax[i0][i1]
即从i0到i1的最小值和最大值(它实际上有n(n-1)/2个元素)。我想说,您应该选择的解决方案取决于三个因素:您可以占用多少内存,您可以花多少时间缓存初始数据结构以简化算法,以及您每次需要实际算法运行的速度。您可以提供更多有关问题限制的详细信息吗?一个简单的方法是使用树结构。树的根将具有整个列表的最小/最大值。然后,它将有两个子项,分别给出前半部分和后半部分的最小/最大值,以此类推。这将允许您对任何子范围使用log(n)算法。如果您能够提供O(n²)
空间,则有一个明显的O(1)
时间算法:只需记录所有minmax[i0][i1]
即从i0到i1的最小值和最大值(实际上有n(n-1)/2个元素)。我想说,您应该选择的解决方案取决于三个因素:您可以占用多少内存,您可以花多少时间缓存初始数据结构以简化算法,以及您每次需要实际算法运行的速度。您可以提供更多关于问题限制的详细信息吗?请注意,因为您正在传递根节点到findRange()
,在最坏的情况下,查找算法仍然是log(n),其中n是整个列表的总长度,而不是子集的长度。@KyleStrand:是的,它的措辞不好。我已经修复了它。请注意,因为您正在将根节点传递到findRange())
,在最坏的情况下,查找算法仍然是log(n),其中n是整个列表的总长度,而不是子集的长度。@KyleStrand:是的,它的措辞不好。我已经修复了它。