给定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中的每个数字,看看它是否在该范围内。
预分类输入 - 对输入数字(O(NlogN))进行排序,然后执行以上操作。可以对完全超出范围的查询进行边界检查,并且不需要迭代(即查询(0,2)像[5,6,7]这样的列表)。这仍然涉及迭代,在最坏的情况下仍然是O(NM)(对吗?)
散列集 - 将输入数组中的每个值添加到散列集中,然后对于查询范围内的每个可能的整数值,检查它是否存在于散列集中。这适用于较小的范围,但基本上是相同的 - >它是O(MX),其中X是查询范围的长度。因此,如果您的查询范围很大(即(-10000000,10000000)),则无法扩展。
我很想听到/了解更好的解决方案! (此问题的替代方法是确定每个查询范围内的数字位数,而不是输出数字)。
请告诉我!
答案 0 :(得分:1)
可以使用扫描线算法在(2*M + N) log (2*M + N)
中完成
创建活动清单:
按位置排序(如果是平局,则必须根据事件进行排序:取决于您的范围是打开还是关闭)。
然后迭代事件:
因此,在您的情况下,事件列表将是
{-100S -10N -2N -1N, 0N, 0N, 0E, 2S, 5E, 8N, 12N, 13S, 16N, 18E}
[(-100, 0)]
。[(-100, 0)]
[]
[(2, 5)]
[]
[(13, 18)]
(13, 18)
。[]
相关:
答案 1 :(得分:0)
我建议对范围进行排序而不是输入数字,然后简单地检查任何给定的输入是否与范围匹配。如果你能在数字列表之前得到范围那么更好。这样你只能迭代数字一次(当你读它们时。)
您仍然必须迭代输入数字列表(没有任何东西可以帮助您),但范围列表应小于数字列表,因此排序和搜索都会更快