兩個排序數組的中位數
1、問題描述
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)).
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
給定兩個大小爲 m 和 n 的有序數組 nums1 和 nums2 。
請找出這兩個有序數組的中位數。要求算法的時間複雜度爲 O(log (m+n)) 。
示例 1:
nums1 = [1, 3]
nums2 = [2]
中位數是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
中位數是 (2 + 3)/2 = 2.5
2、解題思路
2.1 使用二分查找法
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
/*
* 基本思想:
* 每一次判斷,要找的是第k個數,如果在數組1中,第k/2個數比數組個數還要大,就是用最後一個數
用兩個數組中的第k/2個數進行比較,如果第一個數組中的比第二個數組中的大,就能夠將第二個數組中前k/2個數排除在比較範圍之外
這時候,要查找的的就不是第k個數,而是k-k/2個數,
*
*
* left1:表示數組1的左邊界,數組下標
* left2:表示數組2的左邊界,數組下標
*/
int mid_loc;
int pos1, pos2, left1 = 0, left2 = 0;
// 奇偶判斷,奇數爲真,偶數爲假
bool flag_odd_even = (nums1Size + nums2Size) % 2 == 0 ? false : true;
bool found = false;
double result;
int result_pos;
// 根據奇偶數,判斷中位數是第幾位數
if (flag_odd_even) {
//如果是奇數
mid_loc = (nums1Size + nums2Size) / 2 + 1;
} else {
//如果是偶數
mid_loc = (nums1Size + nums2Size) / 2;
}
// 判斷幾種特殊情況,可以直接返回結果
if (nums1Size == 0 && nums2Size != 0 && nums2Size > mid_loc) {
if (flag_odd_even) {
result = nums2[mid_loc - 1];
} else {
result = (1.0 * nums2[mid_loc - 1] + nums2[mid_loc]) / 2;
}
} else if (nums2Size == 0 && nums1Size != 0 && nums1Size > mid_loc) {
if (flag_odd_even) {
result = nums1[mid_loc - 1];
} else {
result = (1.0 * nums1[mid_loc - 1] + nums1[mid_loc]) / 2;
}
} else {
// 使用二分法,進行判斷
while (!found) {
pos1 = (mid_loc / 2) > (nums1Size - left1 - 1) ? nums1Size - 1 : (mid_loc / 2 + left1 - 1);
pos2 = (mid_loc / 2) > (nums2Size - left2 - 1) ? nums2Size - 1 : (mid_loc / 2 + left2 - 1);
if (nums1[pos1] >= nums2[pos2]) {
// 如果第二個已經到了邊界, 在第一個數組中直接找到結果
if (pos2 == (nums2Size - 1)) {
result_pos = mid_loc - (pos2 - left2 + 1) + left1 - 1;
//奇數
if (flag_odd_even) {
result = nums1[result_pos];
} else {
result = (1.0 * nums1[result_pos] + nums1[result_pos + 1]) / 2;
}
found = true;
} else {
mid_loc -= (pos2 - left2 + 1);
left2 = pos2 + 1;
}
} else {
// 如果第一個到了邊界,直接在第二個數組中找到結果
if (pos1 == (nums1Size - 1)) {
result_pos = mid_loc - (pos1 - left1 + 1) + left2 - 1;
//奇數
if (flag_odd_even) {
result = nums2[result_pos];
} else {
result = (1.0 * nums2[result_pos] + nums2[result_pos + 1]) / 2;
}
found = true;
} else {
mid_loc -= (pos1 - left1 + 1);
left1 = pos1 + 1;
}
}
if (!found && mid_loc == 1) {
if (nums1[left1] <= nums2[left2]) {
// 如果是奇數
if (flag_odd_even) {
result = nums1[left1];
} else {
// 第一個條件是邊界保護
if ((left1 < nums1Size - 1) && (nums1[left1 + 1] <= nums2[left2])) {
result = (1.0 * nums1[left1] + nums1[left1 + 1]) / 2;
} else {
result = (1.0 * nums1[left1] + nums2[left2]) / 2;
}
}
} else {
if (flag_odd_even) {
result = nums2[left2];
} else {
// 第一個條件是邊界保護
if ((left2 < nums2Size - 1) && (nums2[left2 + 1] <= nums1[left1])) {
result = (1.0 * nums2[left2] + nums2[left2 + 1]) / 2;
} else {
result = (1.0 * nums2[left2] + nums1[left1]) / 2;
}
}
}
found = true;
}
}
}
return result;
}
2.2 緩衝數組法
這個緩衝法就有點笨拙了,就類似於歸併排序裏面的,將兩個已排好序的數組合並起來,不過我們只需要其中一半即可,這樣就找到中位數了,這種辦法的好處就是思路非常清晰,簡單,但是會佔用額外的空間,並且速度不快;
double findMedianSortedArrays(int *nums1, int nums1Size, int *nums2, int nums2Size) {
/*
* 基本思想:
*
*
*/
int buff_length = (nums1Size + nums2Size) / 2 + 1;
int num = (int*)malloc(sizeof(int)*buff_length);
bool flag_odd_even = (nums1Size + nums2Size) % 2 == 0 ? false : true;
int i=0,j=0;
int count = 0;
double result;
int temp_length = buff_length;
while (temp_length-- ){
if ((i <nums1Size && nums1[i] <= nums2[j]) || j>= nums2Size ){
num[count++] = nums1[i];
i++;
}else if((j < nums2Size && nums2[j] <= nums1[i]) || i >= nums1Size){
num[count++] = nums2[j];
j++;
}
}
if (flag_odd_even){
result = num[buff_length-1];
} else{
result = (1.0 * num[buff_length-2] + num[buff_length-1])/2;
}
return result;
}