1. 程式人生 > >兩個排序陣列中找第k大的數

兩個排序陣列中找第k大的數

一、問題

給定兩個已經排序好的陣列,找到兩者所有元素中第k大的元素

二、解法一:merge--將兩個有序陣列變成一個有序陣列

時間複雜度O(m+n),空間複雜度O(m+n)

/*************************************************
給定兩個已經排序好的陣列,找到兩者所有元素中第k大的元素
Author:tmw
date:2018-3-25
*************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int merge( int* array1, int len1, int* array2, int len2, int K )
{
    int i=0;
    int j=0;
    int k=0;
    if(!array1||!array2||len1==0||len2==0)
        return -1;
    int result[len1+len2];
    while( i<len1 && j<len2 )
    {
        if( array1[i] <= array2[j] )
            result[k++] = array1[i++];
        else
            result[k++] = array2[j++];
    }
    /**array1還有剩餘**/
    while( i<len1 )
        result[k++] = array1[i++];
    /**array2還有剩餘**/
    while( j<len2 )
        result[k++] = array2[j++];

    return result[K-1];
}

三、解法二:遊標計數

    題目只要求第k大的數,沒必要花力氣將陣列全部再排序,可以定義兩個遊標分別指向兩個有序陣列,按序移動,並用count計數,當count等於k時,返回兩個遊標指向的數中最小的那一個。

    時間複雜度O(m+n),空間複雜度O(m+n)

int find_Kth_largeNumber_from2sortedArray( int* array1, int len1, int* array2, int len2, int K )
{
    if(!array1||!array2||len1==0||len2==0)
        return -1;
    int i = 0;
    int j = 0;
    int count = 0;

    while( count<K-1 )
    {
        if( array1[i]<=array2[j] )
            i++;
        else
            j++;
        count++;
    }
    return array1[i]>=array2[j]?array2[j]:array1[i];
}

四、解法三:類二分查詢

充分利用兩個陣列都是有序的條件:
    1)當array1[k/2-1] == array2[k/2-1] 則返回array1[k/2-1]或者array2[k/2-1];
    2)當array1[k/2-1] > array2[k/2-1]  則array2在[0,k/2-1]範圍內的元素一定比array1、array2合併後第k個元素小,可以不用考慮array2在[0,k/2-1]範圍內的元素;

    3)當array1[k/2-1] < array2[k/2-1]  則array1在[0,k/2-1]範圍內的元素一定比array1、array2合併後第k個元素小,可以不用考慮array1在[0,k/2-1]範圍內的元素。

    因此演算法可以寫成一個遞迴的形式,遞迴結束的條件為:
    1)array1[k/2-1] == array2[k/2-1] return array1[k/2-1]
    2)array1或者array2為空時,return array1[k-1]或者array2[k-1]
    3)k==1時,返回min(array1[0],array2[0])

    時間複雜度O(log(m+n))

#define min(a,b) (a<b?a:b)
int Binary_find_Kth( int* array1, int len1, int* array2, int len2, int k )
{
    /**在這裡始終認為len1<len2**/
    if( len1>len2 ) return Binary_find_Kth(array2,len2,array1,len1,k);
    if( len1==0 ) return array2[k-1];
    if( k==1 ) return min(array1[0],array2[0]);

    /**將k分為兩部分,分別在array1和array2陣列上查詢**/
    int k1 = min(k/2,len1);
    int k2 = k-k1;

    /**
        說明array2的k2-1前部分一定在第k大元素之前,因此:
        1)將k2-1這部分全跳過:更新陣列首位地址索引,同時更新陣列長度;
        2)將這k2元素納入已找到的第k大元素範圍內,更新k值:k-k2
    **/
    if( array1[k1-1] > array2[k2-1] )
        return Binary_find_Kth(array1,len1,array2+k2,len2-k2,k-k2);
    /**
        說明array1的k1-1前部分一定在第k大元素之前,因此:
        1)將k1-1這部分全跳過:更新陣列首位地址索引,同時更新陣列長度;
        2)將這k1元素納入已找到的第k大元素範圍內,更新k值:k-k1
    **/
    else if( array1[k1-1] < array2[k2-1] )
        return Binary_find_Kth(array1+k1,len1-k1,array2,len2,k-k1);

    else
        return array1[k1-1];
}

夢想還是要有的,萬一實現了呢~~~ヾ(◍°∇°◍)ノ゙~~