leetcode algo4:Median of Two Sorted Arrays
題目:There
are two sorted arrays nums1 and nums2 of
size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
實現思想:
上述問題是求兩個有序數組的中位數。我們首先想到的方法是:合併兩個有序數組得到一個有序數組,算法複雜度爲:O(m+n),然後直接輸出中位數(其實我們在合併的過程中就可以輸出中位數),但是這個方法複雜度達不到要求。
算法複雜度既然要達到log級別,很大可能上需要利用分治法,而在這一題中如何運用分治法呢?我們有這樣一個直觀上的認識:我們分別取nums1[k/2]和nums2[k/2](k爲中位數的序,從1計數;假設nums1[k/2]和nums2[k/2]都存在),如果nums1[k/2]<nums2[k/2],那麼中位數肯定不在nums1[0]至nums1[k/2]中。通過這個直觀上的認識,我們是不是想到了什麼?我們利用上述的思想每次可以在兩個數組的某一個數組中去掉k*(0.5^n)個元素,直至找到中位數。下面可以通過看看代碼瞭解一下具體的邏輯(leetcode 提交通過, Run Time:6ms)。
package algo4;
public class Solution {
public static void main(String[] args) {
Solution s = new Solution();
int[] nums1 = {5, 23, 222, 23232};
int[] nums2 = {1, 2, 1212, 2222};
System.out.println(s.findMedianSortedArrays(nums1, nums2));
}
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if(nums1.length == 0) {
if(nums2.length % 2 == 0) {
return (nums2[nums2.length/2 - 1] + nums2[nums2.length/2])/2d;
} else {
return nums2[nums2.length/2];
}
}
if(nums2.length == 0) {
if(nums1.length % 2 == 0) {
return (nums1[nums1.length/2 - 1] + nums1[nums1.length/2])/2d;
} else {
return nums1[nums1.length/2];
}
}
int total = nums1.length + nums2.length;
if(total % 2 == 0) {
return (findkth(nums1, 0, nums2, 0, total/2) + findkth(nums1, 0, nums2, 0, total/2 + 1))/2d;
} else {
return findkth(nums1, 0, nums2, 0, total/2 + 1);
}
}
/**
* @param nums1 : 有序數組1
* @param s1 : 有序數組1的起始index(前面的數據都被排除存在中位數的可能了)
* @param nums2 : 有序數組2
* @param s2:有序數組2的起始index
* @param k:中位數在兩個有序數組的剩餘部分(起始index後)上的序
*/
private double findkth(int[] nums1, int s1, int[] nums2, int s2, int k) {
if(s1 == nums1.length) {
return nums2[s2 + k - 1];
}
if(s2 == nums2.length) {
return nums1[s1 + k - 1];
}
if(k == 1) {
if(nums1[s1] < nums2[s2]) {
return nums1[s1];
} else {
return nums2[s2];
}
}
if(nums1.length - s1 < k/2) {
return findkth(nums1, s1, nums2, s2 + k/2, k%2 == 0 ? k/2 : k/2 + 1);
}
if(nums2.length - s2 < k/2) {
return findkth(nums1, s1 + k/2, nums2, s2, k%2 == 0 ? k/2 : k/2 + 1);
}
if(nums1[k/2 + s1 - 1] < nums2[k/2 + s2 - 1]) {
return findkth(nums1, s1 + k/2, nums2, s2, k%2 == 0 ? k/2 : k/2 + 1);
} else if(nums1[k/2 + s1 - 1] > nums2[k/2 + s2 - 1]) {
return findkth(nums1, s1, nums2, s2 + k/2, k%2 == 0 ? k/2 : k/2 + 1);
} else {
if(k % 2 == 0) {
return nums1[k/2 + s1 - 1];
} else {
if(nums1[k/2 + s1] < nums2[k/2 + s2]) {
return nums1[k/2 + s1];
} else {
return nums2[k/2 + s2];
}
}
}
}
/*
private int binarySearch(int[] nums, int v) {
int begin = 0, end = nums.length - 1, medianIndex;
while(true) {
if(begin == end) {
return begin + 1;
}
medianIndex = (begin + end)/2;
if(nums[medianIndex] < v) {
begin = medianIndex + 1;
} else if(nums[medianIndex] > v) {
end = medianIndex;
} else {
return medianIndex + 1;
}
}
}
*/
}