问题陈述:
最近我接受了一道面试题。我只能想到下面的代码,其运行时间为 O(k log n) -
给定 k <= n 个大小为 n 的排序数组,存在一种数据结构,需要 O(kn) 的预处理时间和内存,以在 O(k + log n) 时间内回答迭代搜索查询。
我有 k 个已排序列表,每个列表的大小为 n。目前我已经硬编码了 5 个大小为 3 的已排序列表,但通常可能会很高-
我想在每个 k 个列表中搜索单个元素。
显然,我可以单独地对每个数组进行二进制搜索,这将导致 O(k log n) 的时间复杂度,其中 k 是已排序数组的数量。
我们能否在 O(k + log n) 的时间复杂度内完成,其中 k 是已排序数组的数量?因为现在我们正在做相同的搜索 k 次,所以我认为可能有更好的方法 -
private List<List<Integer>> dataInput;
public SearchItem(final List<List<Integer>> inputs) {
dataInput = new ArrayList<List<Integer>>();
for (List<Integer> input : inputs) {
dataInput.add(new ArrayList<Integer>(input));
}
}
public List<Integer> getItem(final Integer x) {
List<Integer> outputs = new ArrayList<Integer>();
for (List<Integer> data : dataInput) {
int i = Collections.binarySearch(data, x); // binary searching the item
if (i < 0)
i = -(i + 1);
outputs.add(i == data.size() ? null : data.get(i));
}
return outputs;
}
public static void main(String[] args) {
List<List<Integer>> lists = new ArrayList<List<Integer>>();
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(3, 4, 6));
List<Integer> list2 = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
List<Integer> list3 = new ArrayList<Integer>(Arrays.asList(2, 3, 6));
List<Integer> list4 = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
List<Integer> list5 = new ArrayList<Integer>(Arrays.asList(4, 8, 13));
lists.add(list1);
lists.add(list2);
lists.add(list3);
lists.add(list4);
lists.add(list5);
SearchItem search = new SearchItem(lists);
System.out.println(dataInput);
List<Integer> dataOuput = search.getItem(5);
System.out.println(dataOuput);
}
希望我的新代码能够输出与之前代码相同的结果,并且时间复杂度为O(k + log n)
。
这种需求是否可行?有没有人可以根据我的示例提供一个实现方法呢?
list1 = [0,..,n]
,list2 = [n,...,n]
,list3 = [n,...,2*n]
。当合并时,你可以得到列表list1 + list2 + list3
。如果现在搜索元素n
,则列表1和列表3的结果相差n
个元素,那么如何在O(log n)
的时间内找到它们呢?你可以将所有的n
压缩成单个节点,但仍然无法回答前驱/后继查询(虽然这里没有明确要求,但也可以有效地实现)。 - Niklas B.