1- 思路
- 1- 中位数的定义
- 如果合并后的数组是 奇数位,中位数就是中间的数
- 如果合并后的数组是 偶数位,中位数就是中间两个数的平均
递归法
① 问题抽象:
- 将问题抽象成寻找两个数组中,第
k
大的数是多少即可解决这个问题,其中k = (n+m)/2
- 比较 A 数组,B 数组的
k/2
是多少
❗① 如果 A[k/2] < B[k/2]
,此时目标答案 k
的值,一定不在 A 的前 [k/2]
个元素中
- 统计AB数组中 小于等于
A[k/2]
元素的个数有多少- A 中小于等于
A[k/2]
元素的个数有k/2
个。 - 在 B 中由于
B[k/2] > A[k/2]
,所以B中小于等于A[k/2]
元素的个数小于k/2
个。
- A 中小于等于
- 因此直接删除 A[0:k/2] 的元素
❗② 如果 A[k/2] > B[k/2]
,此时目标答案 k
的值,一定不在 B 的前 [k/2]
个元素中。
❗③ 如果 A[k/2] = B[k/2]
,此时目标答案 k
的值,就是 A[k/2] = B[2/k]
② 结论:
- 每一次比较都可以删除 [k/2] 个元素
- 当 k = 1 时候就可以找到最终结果,每次递归法 因此时间复杂度为
O(log k)
2- 实现
⭐4. 寻找两个正序数组的中位数——题解思路
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
// 1. 数据结构
int len1 = nums1.length;
int len2 = nums2.length;
// 1.1 保证奇偶
int left = (len1+len2+1)/2;
int right = (len1+len2+2)/2;
return((findK(nums1,0,len1-1,nums2,0,len2-1,left)+findK(nums1,0,len1-1,nums2,0,len2-1,right))*0.5);
}
public int findK(int[] nums1,int start1,int end1,int[] nums2,int start2,int end2,int k){
// 1. 保持 1 最长
int len1 = end1-start1+1;
int len2 = end2-start2+1;
if(len1>len2) return findK(nums2,start2,end2,nums1,start1,end1,k);
// 终止条件
if(len1==0) return nums2[start2+k-1];
if(k == 1) return Math.min(nums1[start1],nums2[start2]);
// 3.递归逻辑
int i = start1 + (Math.min(len1,k/2)-1);
int j = start2 + (Math.min(len2,k/2)-1);
// 判断
if(nums1[i]>nums2[j]){
return findK(nums1,start1,end1,nums2,j+1,end2,k-(j-start2+1));
}else{
return findK(nums1,i+1,end1,nums2,start2,end2,k-(i-start1+1));
}
}
}