题目描述
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
解法1
依次遍历这两个有序数组的元素,如果长度分别为len1,len2直到找到第(len1+len2)/2的元素

class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
int i = 0;
int j = 0;
int[] array = new int[(n1 + n2) / 2 + 1];
int index = 0;
// 找到第(n1+n2)/2小的数
while(index < array.length) {
if (i < n1 & j < n2) {
if (nums1[i] < nums2[j]) {
array[index++] = nums1[i++];
} else {
array[index++] = nums2[j++];
}
} else if (i >= n1) {
array[index++] = nums2[j++];
} else {
array[index++] = nums1[i++];
}
}
if((n1 + n2) % 2 == 0) {
return 0.5*(array[array.length - 1] + array[array.length - 2]);
} else {
return array[array.length - 1];
}
}
}
时间复杂度O(m+n)
空间复杂度O(m+n)
解法2
分治法解题思路:
1. 首先是递归函数的定义,作用是寻找两个有序数组nums1中[left1, right1]和nums2数组[left2,right2]范围内第k小的数,k从1开始
2. 用n1纪录nums1数组中寻找范围的长度,用n2来记录nums2数组中寻找范围的长度
3. 如果要寻找的k大于n1 + n2,直接抛出异常
4. 如果n1>n2,将递归调用该函数,不过将与nums1数组有关的参数与nums2有关的参数进行换位,这样确保后期操作都是在n1 <= n2的条件下进行的。
5. 终止条件:
a. 当n1为0时,说明直邮一个数组中有元素,直接取该数组中第left2+k-1位元素即可
b. 当k为1时,说明我们要取的两个有序数组中的最小值直接返回两个数组第一个元素较小值即可

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
if (n1 == 0 && n2 == 0) {
throw new IllegalArgumentException("两个数组长度为0");
}
int mid1 = findKthInTwoArrays(nums1, 0, n1-1, nums2, 0, n2-1, (n1 + n2) /2 + 1);
if ((n1 + n2) % 2 != 0) {
return mid1;
} else {
int mid2 = findKthInTwoArrays(nums1, 0, n1-1, nums2, 0, n2-1, (n1+n2)/2);
return 0.5* (mid1 + mid2);
}
}
private int findKthInTwoArrays(int[] nums1, int left1, int right1, int[] nums2, int left2, int right2, int k) {
int n1 = right1 - left1 + 1;
int n2 = right2 - left2 + 1;
if (k > n1 + n2) {
throw new IllegalArgumentException("k的值过大");
}
if (n1 == 0) {
return nums2[left2 + k - 1];
}
if (n2 == 0) {
return nums1[left1 + k - 1];
}
if (k == 1) {
return Math.min(nums1[left1], nums2[left2]);
}
int i = Math.min(n1, k/2);
int j = Math.min(n2, k/2);
if(nums1[left1 + i - 1] > nums2[left2 + j - 1]) {
return findKthInTwoArrays(nums1, left1, right1, nums2, left2 + j, right2, k - j);
}else {
return findKthInTwoArrays(nums1, left1 + i, right1, nums2, left2, right2, k - i);
}
}
}
时间复杂度O(lg(m+n))
空间复杂度O(n)
来源:https://www.cnblogs.com/ecnu-llblog/p/10137662.html
