查询数组

时间:2017-12-07 16:57:34

标签: 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中的每个数字,看看它是否在该范围内。

预分类输入 - 对输入数字(O(NlogN))进行排序,然后执行以上操作。可以对完全超出范围的查询进行边界检查,并且不需要迭代(即查询(0,2)像[5,6,7]这样的列表)。这仍然涉及迭代,在最坏的情况下仍然是O(NM)(对吗?)

散列集 - 将输入数组中的每个值添加到散列集中,然后对于查询范围内的每个可能的整数值,检查它是否存在于散列集中。这适用于较小的范围,但基本上是相同的 - >它是O(MX),其中X是查询范围的长度。因此,如果您的查询范围很大(即(-10000000,10000000)),则无法扩展。

我很想听到/了解更好的解决方案! (此问题的替代方法是确定每个查询范围内的数字位数,而不是输出数字)。

请告诉我!

2 个答案:

答案 0 :(得分:1)

可以使用扫描线算法在(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:活动间隔:[]

相关:

答案 1 :(得分:0)

我建议对范围进行排序而不是输入数字,然后简单地检查任何给定的输入是否与范围匹配。如果你能在数字列表之前得到范围那么更好。这样你只能迭代数字一次(当你读它们时。)

您仍然必须迭代输入数字列表(没有任何东西可以帮助您),但范围列表小于数字列表,因此排序和搜索都会更快