兩個排序陣列中找第k大的數
阿新 • • 發佈:2019-01-05
一、問題
給定兩個已經排序好的陣列,找到兩者所有元素中第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];
}
夢想還是要有的,萬一實現了呢~~~ヾ(◍°∇°◍)ノ゙~~