【发布时间】:2013-02-16 18:18:26
【问题描述】:
这是一道面试题。
给定一个整数数组和一个流区间(整数对),找出落在流的每个区间内的数组元素。你会使用什么数组预处理?
【问题讨论】:
-
我个人会选择桶排序之类的东西。制作 n 个桶,其中 n 是间隔数。然后在 O(n) 中你会得到你的结果。
这是一道面试题。
给定一个整数数组和一个流区间(整数对),找出落在流的每个区间内的数组元素。你会使用什么数组预处理?
【问题讨论】:
一种选择是通过将数组按升序排序来预处理数组。完成此操作后,您可以通过对已排序的数组进行两次二进制搜索来找到位于某个区间内的所有元素 - 一次查找大于或等于区间开始的第一个元素,另一次查找最后一个元素不大于区间的端点 - 然后遍历数组以输出该范围内的所有元素。
如果您使用快速排序或堆排序等标准排序算法,这需要 O(n log n) 时间进行预处理,但如果您使用基数排序(这里 U 是最大的),则可以在 O(n log U) 时间内完成范围内的整数)。然后每个查询花费时间 O(log n + k),其中 n 是元素的数量,k 是范围内的元素数量。
如果您想变得花哨,您可以使用van Emde Boas tree(一种用于存储整数的专用数据结构)以指数方式加快速度。如果您正在使用的最大整数值是 U,那么您可以在 O(n log log U) 时间内构建结构,然后在 O(log log U) 时间内进行端点范围搜索。然后,您可以在 O(log log U) 的时间内找到范围内的所有元素,给出一个 O(k log log U) 算法来查找范围内的所有匹配项。
希望这会有所帮助!
【讨论】:
对数组进行排序,然后进行二分查找,查找数组中大于区间start的第一个元素的索引,然后再次查找小于区间end的第一个元素,并返回所有的之间的整数。对于每个查找,它将是 O(log N),其中 N 是整数的数量。
【讨论】:
答案取决于您的要求:
你说 M 有多少个区间?
当然,使用 M * O(N logN) 是多余的,尤其是当 M 很大并且间隔也很大时。
另一种方法:使用 O(N) 额外空间。
prefix[i] = number of numbers in range 0 to i
可以在 O(N) 时间内完成。
现在,每个查询都需要 O(1) 时间:
query[l,r] = prefix[r] - prefix[l - 1] + 1
所以总时间复杂度是O(N logN + M)
【讨论】:
如何根据元素索引数组?
for (i in original_array) indexed_array[original_array[i]] = original_array[i]
for (j in stream) {
for (k=stream[j][0]; k<=stream[j][1]; k++)
if (indexed_array[k]) return indexed_array[k]
}
或者用索引代替整数:
for (i in original_array) indexed_array[original_array[i]] = i
【讨论】: