問題:有兩個有序的數組nums1和nums2,長度分別爲m和n,找到兩個有序數組的中位數,運行時間複雜度爲
例如:
nums1 = [1,3],nums2 = [2],中位數爲2.0
nums1 = [1,2],nums2 = [3,4],中位數爲2.5
解決思路:如果沒有要求時間複雜度,可以對兩個數組的每個元素依次比較排序或者使用歸併排序,這裏要求時間複雜度爲
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int k = (m+n+1)/2;//第k個數
if((m+n)%2==0){//長度爲偶數情況
return (findKth(nums1,nums2,0,0,m,n,k)+findKth(nums1,nums2,0,0,m,n,k+1))/2;
}else{
return findKth(nums1,nums2,0,0,m,n,k);//奇數情況
}
}
private double findKth(int[]arr1,int[]arr2,int start1,int start2,int len1,int len2,int k){
if(len1>len2){//保證數組1的長度小於數組2
return findKth(arr2,arr1,start2,start1,len2,len1,k);
}
if(len1==0){//當數組1長度爲0
return arr2[start2+k-1];
}
if(k == 1){//如果k爲1,返回兩個數組的最小值
return Math.min(arr1[start1],arr2[start2]);
}
//將k分爲數組1的p1範圍和數組2的p2範圍
int p1 = Math.min(k/2,len1);
int p2 = k-p1;
//判斷k是落在哪個區間範圍
if(arr1[start1+p1-1]<arr2[start2+p2-1]){
return findKth(arr1,arr2,start1+p1,start2,len1-p1,len2,k-p1);
}else if(arr1[start1+p1-1]>arr2[start2+p2-1]){
return findKth(arr1,arr2,start1,start2+p2,len1,len2-p2,k-p2);
}else{
return arr1[start1+p1-1];
}
}
如果沒有限制複雜度,可以採用歸併計數法,這時的複雜度爲
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n = nums2.length;
int m = nums1.length;
int total = m+n;
if(total%2==0){//長度爲偶數
return (findKthFei(nums1,nums2,total/2)+findKthFei(nums1,nums2,total/2+1))/2.0;
}else{//爲奇數時
return findKthFei(nums1,nums2,total/2+1);
}
}
private double findKthFei(int[]arr1,int[]arr2,int k){
int p = 0,q = 0;//兩個指針,指向數組底部,比較指針大小
//判斷k的範圍
for(int i = 0;i<k-1;i++){
if(p>=arr1.length && q<arr2.length){
q++;
}else if(q>=arr2.length && p<arr1.length){
p++;
}else if(arr1[p]>arr2[q]){
q++;
}else{
p++;
}
}
if(p>=arr1.length){
return arr2[q];
}else if(q>=arr2.length){
return arr1[p];
}else{
return Math.min(arr1[p],arr2[q]);
}
}
}