我正在试图找到一种方法将标记为A1的n个数组合并到An。
每个数组Ai都是{1..i}
的子集。例如,A3可以是{1}或{3}或{1,3}。请注意,每个数组都已排序。
例如n = 8, A1={}, A2={2}, A3={2,3}, A4={1,4}, A5=A6=A7={}, A8={6}
,将所有这些合并为{1,2,3,4,6}。
我正试图找出一种方法来做到这一点比O(n ^ 2)更快,这很明显,因为所有数组中都有O(n ^ 2)个总元素我们可以创建一个大小为n的数组,并尝试将每个元素放入一个桶中。
答案 0 :(得分:0)
如果你有k
个整数数组,其中包含n
项的总和,那么你可以使用O(k)额外空格在O(n log k)时间内合并它们。以下是它的完成方式:
首先,创建一个名为pqitem
的类型,它将数组和当前索引保存到数组中。例如:
class pqitem
int[] A;
int i;
然后,创建一个优先级队列(min-heap)来保存pqitem
个实例。比较函数应该比较A[i]
,因此堆中的项目的排列使得当前项目最小的数组位于根目录。
对于每个数组,创建一个pqitem
实例来保存数组。将i
字段初始化为0.插入优先级队列。
现在,不断删除堆中的最低项,输出当前值,增加i
,然后将项目添加回堆i < A.length
。那就是:
myHeap = new heap()
for each array
item = new pqitem(array, 0)
myHeap.Add(item)
while (myHeap.count > 0)
item = myHeap.pop()
output item.A[item.i] // output or add to new array, etc.
++item.i
if (item.i < item.A.length)
myHeap.Add(item)
在您的情况下,您希望防止重复。因此,您稍微修改合并循环以跟踪最后一项输出,并防止输出重复项。
// keep track of the previous item
prev = -1 // Initialize to a value that won't appear in the lists
while (myHeap.count > 0)
item = myHeap.pop()
// skip duplicates
if (item.A[item.i] != prev)
output item.A[item.i] // output or add to new array, etc.
prev = item.A[item.i]
++item.i
if (item.i < item.A.length)
myHeap.Add(item)
答案 1 :(得分:0)
您需要一个容器,该容器将包含k
数组的i
项,索引i
和索引k
。
public class Node {
int item, arrIndx, itemIndx;
public Node(int a, int b, int c) {
this.item = a;
this.arrIndx = b;
this.itemIndx = c;
}
}
使用minHeap(优先级队列按升序排序其元素)以包含Node
。
首先,对于每个数组,将其第一个元素推入minHeap。 minHeap如何保存第一个n
个排序元素。
现在逐个从minHeap中弹出前面元素,这是所有数组项中最小的元素并将其放入输出数组中。在弹出k
数组的任何i
元素期间,将k + 1
数组的i
元素放入队列。这样我们就可以确定,我们正在推动当前最小元素的最小元素。
继续此过程,直到从minHeap推送和弹出所有数组元素。
示例Java代码段如下所示:
public List<Integer> mergekSortedArrays(int[][] arrays) {
List<Integer> result = new ArrayList<Integer>();
if (arrays == null || arrays.length == 0) {
return result;
}
PriorityQueue<Node> minHeap = new PriorityQueue<Node>(arrays.length,
new Comparator<Node>() {
public int compare(Node lhs, Node rhs) {
return lhs.item - rhs.item;
}
}
);
// O(n log n)
for (int i = 0; i < arrays.length; i++) {
if (arrays[i].length > 0) {
minHeap.offer(new Node(arrays[i][0], i, 0));
}
}
Node node;
// O((N - n)log n)
while (!minHeap.isEmpty()) {
node = minHeap.poll();
result.add(node.item);
if (node.itemIndx + 1 < arrays[node.arrIndx].length) {
minHeap.offer(new Node(arrays[node.arrIndx][node.itemIndx + 1], node.arrIndx, node.itemIndx + 1));
}
}
return result;
}
时间复杂度为O(N log n)
,其中n
是数组的数量,N
是这些数组中所有元素的数量。