題目:
給定兩個大小爲 m 和 n 的有序數組 nums1 和 nums2。
請你找出這兩個有序數組的中位數,並且要求算法的時間複雜度爲 O(log(m + n))。
你可以假設 nums1 和 nums2 不會同時爲空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
則中位數是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
則中位數是 (2 + 3)/2 = 2.5
思路:
首先判斷兩個數組總長度爲奇數還是偶數,奇數則只需找最終的一個元素即可,偶數則需要尋找下標爲len/2和len/2-1的兩個元素。然後再就是找中間元素的步驟了,以總長度爲奇數爲例,在兩個數組合並的大數組中中位數的下標爲(len1+len2)/2,然後分別兩個數組從前向後比較,找到下標爲(len1+len2)/2的元素
代碼:
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int point1 = 0, point2 = 0;
double mid;
if ((nums1.length + nums2.length) % 2 == 0) {
int median1 = 0, median2 = 0;
int medianIndex = (nums1.length + nums2.length) / 2;
for (int i = 0; i <= medianIndex; i++) {
median2 = median1;
if (point1 >= nums1.length) {
median1 = nums2[point2];
point2++;
continue;
}
if (point2 >= nums2.length) {
median1 = nums1[point1];
point1++;
continue;
}
if (nums1[point1] < nums2[point2]) {
median1 = nums1[point1];
point1++;
} else {
median1 = nums2[point2];
point2++;
}
}
mid = (median1 + median2) / 2.0;
} else {
int median = 0;
int medianIndex = (nums1.length + nums2.length) / 2;
for (int i = 0; i <= medianIndex; i++) {
if (point1 >= nums1.length) {
median = nums2[point2];
point2++;
continue;
}
if (point2 >= nums2.length) {
median = nums1[point1];
point1++;
continue;
}
if (nums1[point1] < nums2[point2]) {
median = nums1[point1];
point1++;
} else {
median = nums2[point2];
point2++;
}
}
mid = median;
}
return mid;
}
時間複雜度爲O(m+n)
改進:
參考文章:https://segmentfault.com/a/1190000002988010
代碼:
public static double findMedianSortedArrays1(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int k = (m + n) / 2;
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+1);
}
}
private static double findKth(int[] arr1, int[] arr2, int start1, int start2, int len1, int len2, int k){
// 保證arr1是較短的數組
if(len1>len2){
return findKth(arr2,arr1,start2,start1,len2,len1,k);
}
if(len1==0){
return arr2[start2 + k - 1];
}
if(k==1){
return Math.min(arr1[start1],arr2[start2]);
}
int p1 = Math.min(k/2,len1) ;
int p2 = k - p1;
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];
}
}
時間複雜度:O(log(m+n))