Algorithm 查询数组中数字的范围
给定N个输入整数和M个查询范围,输出属于每个查询范围的整数集(两个边界都包含在内)。例如:Algorithm 查询数组中数字的范围,algorithm,sorting,math,Algorithm,Sorting,Math,给定N个输入整数和M个查询范围,输出属于每个查询范围的整数集(两个边界都包含在内)。例如: N = [-10, -1, -2, 0, 0, 8, 12, 16] M = [(-100, 0), (2, 5), (13, 18)] 答案/输出将是: [-10, -1, -2, 0, 0] [] [16] 我一直在试图找到最佳的解决方案,并且正在努力想出一些在最坏的情况下比O(N*M)更好的方法。到目前为止,我考虑的方法有: 暴力-对于每个查询,检查N中的每个数字,看看它是否在范围内 预分类输入
N = [-10, -1, -2, 0, 0, 8, 12, 16]
M = [(-100, 0), (2, 5), (13, 18)]
答案/输出将是:
[-10, -1, -2, 0, 0]
[]
[16]
我一直在试图找到最佳的解决方案,并且正在努力想出一些在最坏的情况下比O(N*M)更好的方法。到目前为止,我考虑的方法有:
暴力-对于每个查询,检查N中的每个数字,看看它是否在范围内
预分类输入-对输入数字进行排序(O(NlogN)),然后执行上述操作。可以对完全超出范围的查询进行边界检查,并消除迭代的需要(例如,对[5,6,7]之类的列表进行查询(0,2))。这仍然需要迭代,在最坏的情况下仍然是O(NM)(对吗?)
哈希集-将输入数组中的每个值添加到哈希集中,然后针对查询范围内的每个可能整数值,检查哈希集中是否存在该整数值。这适用于较小的范围,但基本上是相同的->它是O(MX),其中X是查询范围的长度。因此,如果您的查询范围很大(即(-10000000,10000000)),它将无法扩展
我希望听到/了解更好的解决方案!(这个问题的另一个选择是确定每个查询范围内的数字,而不是输出数字)
请让我知道 我建议对范围进行排序,而不是对输入数字进行排序,然后简单地检查是否有任何给定的输入与某个范围匹配得更好,如果您可以在数字列表之前获得范围,那么您只能对数字进行一次迭代(当您读取它们时) 您仍然需要迭代输入数字列表(在这方面没有任何帮助),但是范围列表应该比数字列表小,因此排序和搜索都会更快。可以在
(2*M+N)log(2*M+N)
中使用扫描线算法完成
创建事件列表:
- 来自N的数字
- 间隔从M开始
- 从M开始的间隔结束
- 如果是开始间隔,则将其添加到当前打开的间隔中
- 如果是结束间隔,则将其从当前打开的间隔中删除
- 如果是N中的数字,则将其添加到所有打开的间隔中
{-100S -10N -2N -1N, 0N, 0N, 0E, 2S, 5E, 8N, 12N, 13S, 16N, 18E}
- -100S:修改活动间隔
[(-100,0)]
- -10N,-2N,-1N,0N,0N:将其添加到
[(-100,0)]
- -0E:活动间隔:
[]
- 2S:有效间隔:
[(2,5)]
- 5E:活动间隔:
[]
- 8N、12N:将其添加到无间隔
- 13S:有效间隔:
[(13,18)]
- 16N:将其添加到间隔
(13,18)
- 18E:活动间隔:
[]
(N+M)log(N+M)
中应该是可行的。这是有道理的,对范围进行排序可能会导致速度优化。这仍然是O(N*M)最坏的情况,对吗?这太神奇了,我从来没有听说过扫描线算法。最后一件事,是否可以解释为什么它是O(M+N(log(M+N)),我可以理解它来自排序(并且可以看到添加查询范围如何改变典型的排序运行时)。它是否简单到:既然列表现在是M+N,排序需要(M+N)log(M+N)时间?(2*M+N)log(2*M+N)
来自对所有事件的排序,有2M+N
事件。太好了-这很有意义。谢谢!