博客转载请注明地址:
题目描述
题目地址:https://leetcode.com/problems/median-of-two-sorted-arrays/
给出两个有序数组,求两个有序数组合并在一起的中位数是多少?
考察点
- 二分查找,分治
- 分类讨论
思路
传统的二分查找在 [L,R] 区间求出满足条件的值。该题是一个举一反三,希望在区间 ([L1,R1],[L2,R2]) 查找出满足条件的值。
转换问题
1. 将题目求中位数转换成:在合并的数组中,找到第k小的数。
假设合并后的数组大小为n,arr表示合并后的数组
那么:
sum=(arr[(n+1)/2]+arr[(n+2)/2])/2.0
枚举一下,就知道这个式子的正确性。
- 在合并后的数组中,中arr_1
不断缩小寻找区间
假设当前的寻找区间为
([L1,R1],[L2,R2])
,
mid1=(L1+R1)/2
;
mid2=(L2+R2)/2
;
maxNum=max(arr1[mid1],arr2[mid2])
如果将这mid_1+mid_2个数字组合在一起
Code
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int L[2], R[2], len[2];
int *arr[2];
int mid[2];
int mid_len[2];
int min_p, max_p;
int dlt_len;
double sum;
len[0] = nums1.size();
len[1] = nums2.size();
arr[0] = new int[len[0] + 2];
arr[1] = new int[len[1] + 2];
for(int i = 1; i <= len[0]; i++)
arr[0][i] = nums1[i-1];
for(int i = 1; i <= len[1]; i++)
arr[1][i] = nums2[i-1];
mid_len[0] = (len[0] + len[1] + 1) >> 1;
mid_len[1] = (len[0] + len[1] + 2) >> 1;
if(!len[0] || !len[1]){
if(!(len[0]^len[1]))
return 0.0;
else
return (arr[!len[0]][mid_len[0]] + arr[!len[0]][mid_len[1]] ) / 2.0;
}
L[0] = 0; R[0] = len[0];
L[1] = 0; R[1] = len[1];
arr[0][0] = arr[1][0] = min(arr[0][1], arr[1][1]);
arr[0][len[0]+1] = arr[1][len[1]+1] = max(arr[0][len[0]], arr[1][len[1]]);
while(true){
mid[0] = (L[0] + R[0]) >> 1;
mid[1] = (L[1] + R[1]) >> 1;
max_p = arr[1][mid[1]] >= arr[0][mid[0]];
min_p = !max_p;
dlt_len = mid[0] + mid[1] - mid_len[0];
if(dlt_len == 0){
if(arr[min_p][mid[min_p]+1] >= arr[max_p][mid[max_p]]){
break;
}else{
R[max_p] = mid[max_p] - 1;
L[min_p] = mid[min_p] + 1;
}
}else if(dlt_len > 0){
R[max_p] = mid[max_p] - 1;
}else{ // < 0
L[min_p] = mid[min_p];
min_p = !(arr[0][L[0] + 1] <= arr[1][L[1]+1]);
L[min_p]++;
}
}
sum = arr[max_p][mid[max_p]];
if(mid_len[0] != mid_len[1]){
sum += min(arr[0][mid[0]+1], arr[1][mid[1]+1]);
sum /= 2;
}
return sum;
}
};