给定两个未排序的int数组,在合并的排序数组中找到第k个元素。 例: int [] a = [3 1 7] int [] b = [4 9] k:3 return 4(非零基础索引)
请不要提供合并两个数组并排序并找到第N个元素的直接解决方案。我正在寻找更有效的解决方案,即使用Heap,QuickSort。并确保数组未排序。
P.S:我知道上面有许多类似的问题在SO中发布但我无法在其中找到任何正确的实施方式。答案 0 :(得分:1)
就目前而言,你的榜样是错误的。
假设它的int [] a = [3 1 7] int [] b = [4 9] k:3返回7.
遍历两个数组并推送到min-heap
。完成后,从堆中弹出k
次,您将获得合并数组中的kth (largest)
元素。
PriorityQueue<Integer> minHeap=new PriorityQueue();
for (Integer i : a)
{
minHeap.add(i);
}
for (Integer i : b)
{
minHeap.add(i);
}
int count=1;// 1 based index
while(!minHeap.isEmpty())
{
Integer head=minHeap.poll();
count++;
if(count==k)
return head;
}
以上代码未经测试。但它应该大致如上所述。
答案 1 :(得分:0)
这个问题的一般术语是Selection Algorithm,维基百科有一篇很棒的文章。
找到两个未排序数组的第k个元素相当于找到一个第k个元素 - 只是假装你已经连接了两个。链接页面中的一个简单算法是Quickselect,它本质上是Quicksort,但只递归到包含第k个元素的一半。从本质上讲,
Use the first element as the pivot
Iterate over the array, assigning items <= to the pivot to one array, and > to another, until an array has grown large enough that it must contain the desired element
Recurse on that array, offsetting k if necessary
答案 2 :(得分:0)
使用快速选择算法的C#代码:
private void MergeUnsortedArray(int[] A1, int[] A2)
{
int[] c = new int[A1.Length + A2.Length];
int length = 0;
for (int i = 0; i < A1.Length; i++)
{
c[i] = A2[i];
length++;
}
for (int j = 0; j < A2.Length; j++)
{
c[length + j + 1] = A2[j];
}
quickselect(c, 0, c.Length, 3);
}
private int quickselect(int[] G, int first, int last, int k)
{
if (first <= last)
{
int pivot = partition(G, first, last);
if (pivot == k)
{
return G[k];
}
if (pivot < k)
{
return quickselect(G, first, pivot - 1, k);
}
return quickselect(G, pivot + 1, last, k);
}
return 0;
}
private int partition(int[] G, int first, int last)
{
int pivot = (first + last) / 2;
swap(G, last, pivot);
for (int i = first; i < last; i++)
{
if (G[i] < G[last])
{
swap(G, i, first);
first++;
}
}
swap(G, first, last);
return first;
}
private void swap(int[] G, int x, int y)
{
int tmp = G[x];
G[x] = G[y];
G[y] = tmp;
}