从两个未排序的数组中找到第N个元素

时间:2014-08-12 16:17:15

标签: arrays sorting data-structures

给定两个未排序的int数组,在合并的排序数组中找到第k个元素。 例: int [] a = [3 1 7] int [] b = [4 9] k:3 return 4(非零基础索引)

请不要提供合并两个数组并排序并找到第N个元素的直接解决方案。我正在寻找更有效的解决方案,即使用Heap,QuickSort。并确保数组未排序。

P.S:我知道上面有许多类似的问题在SO中发布但我无法在其中找到任何正确的实施方式。

3 个答案:

答案 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;
    }