给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
public class Solution {
public double findMedianSortedArrays(int A[], int B[]) {
int n = A.length + B.length;
// 两个数组长度加起来是偶数,找到中间两个数
if (n % 2 == 0) {
// 第(n / 2)个数
int a = findKth(A, 0, B, 0, n / 2);
// 第(n / 2 + 1)个数
int b = findKth(A, 0, B, 0, n / 2 + 1);
return (a + b) / 2.0;
}
// 两个数组长度加起来是奇数,找到第(n / 2 + 1)个数,就是中位数
return findKth(A, 0, B, 0, n / 2 + 1);
}
/**
* 返回两个数组中从小到大的第 k个数
* @param A
* @param startOfA A数组开始下标,用来表示删掉以后哪些数还是有效的
* @param B
* @param startOfB B数组开始下标,用来表示删掉以后哪些数还是有效的
* @param k AB数组合起来 C数组中的第几个数,注意不是下标
* @return
*/
public static int findKth(int[] A, int startOfA, int[] B, int startOfB, int k) {
// A数组空了
if (startOfA >= A.length) {
// 返回 B的第k个数
return B[startOfB + k - 1];
}
if (startOfB >= B.length) {
return A[startOfA + k - 1];
}
if (k == 1) {
return Math.min(A[startOfA], B[startOfB]);
}
// 找到 A、B数组中的第 k/2个数,在数组中下标就是k / 2 - 1
// 当某一个数组没有 k/2 个之后,用最大值替代
int halfKthOfA = startOfA + k / 2 - 1 < A.length ? A[startOfA + k / 2 - 1] : Integer.MAX_VALUE;
int halfKthOfB = startOfB + k / 2 - 1 < B.length ? B[startOfB + k / 2 - 1] : Integer.MAX_VALUE;
// 比较这两个数的大小
if (halfKthOfA < halfKthOfB) {
// 如果 A的第 k/2个位置比 B小,则丢掉 A前 k/2个,更新 A起始位置
return findKth(A, startOfA + k / 2, B, startOfB, k - k / 2);
} else {
return findKth(A, startOfA, B, startOfB + k / 2, k - k / 2);
}
}
}
思路分析:
先看两个数组总数加起来是奇数还是偶数,如果是奇数则是合起来数组中(length = n)的第n/2+1个,如果是偶数则是中间两个数的平均数,中间两个数是合起来数组中的第n/2和n/2+1个
举个栗子
- 当合起来数组长度是奇数时
arrA = [1,3,5,7]
arrB = [2,4,6,8,10]
合起来后:
arrC = [1,2,3,4,5,6,7,8,10] // 5是中位数,是数组中的第 5(9/2+1)个数
- 当合起来数组长度是偶数时
arrA = [1,3,5,7]
arrB = [2,4,6,8]
合起来后:
arrC = [1,2,3,4,5,6,7,8]
// 中位数:(4+5)/2.0=4.5,是数组中第 4(8/2)和第 5(8/2+1)个数的平均数
根据长度的奇偶性,转化为找两个数组合起来的第k个数
对于奇数的情况,要找第k = 5个数,比较A,B数组中第2(k / 2)个数的大小,第2个数的位置为k / 2 - 1 = 1

丢掉A数组的前两个数,然后在剩下的A和B中找第k = k - k / 2 = 3个数,比较A,B数组中第1(k / 2)个数的大小,第1个数的位置为k / 2 - 1 = 0

丢掉B数组的前一个数,然后在剩下的A和B中找第k = k - k / 2 = 2个数,比较A,B数组中第1(k / 2)个数的大小,第1个数的位置为k / 2 - 1 = 0

丢掉B数组的前一个数,然后在剩下的A和B中找第k = k - k / 2 = 1个数,比较A,B数组中第1(k / 2)个数的大小,第1个数的位置为k / 2 - 1 = 0

k = 1,直接返回 5
对于偶数的情况类似,只不过要找两个数而已
395

被折叠的 条评论
为什么被折叠?



