题目描述:
给定两个大小为 m
和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的思路没有那么复杂,就是将两个数组进行拼接,然后排序,最后取出中间的那个数字,当然我们要判断是偶数还是奇数
这种方法虽然容易懂,但是效率就比较低了
代码:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
//System.arraycopy(arg0, arg1, arg2, arg3, arg4);
int len = nums1.length + nums2.length;
int[] c= new int[nums1.length + nums2.length];
System.arraycopy(nums1, 0, c, 0, nums1.length);
System.arraycopy(nums2, 0, c, nums1.length, nums2.length);
Arrays.sort(c);
//是奇数的话就取出其中一个
if((len & 1) == 1){
return (double)c[len / 2];
}else {
return (double)((c[len/2 - 1] + c[len/2])/2.0);
}
}
}
但是乍一看还是可以的
排名靠前的代码,注意要利用有序这个条件来进行,我上面那个代码就没有考虑有序这个条件,因此要重复利用题目已给的条件,从而降低复杂度
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int nums2length = nums2.length;
int[] r = new int[nums1.length + nums2length];
int index = 0;
int j = 0;
for (int num : nums1) {
while (j < nums2length && num > nums2[j]) {
r[index] = nums2[j];
j++;
index++;
}
r[index] = num;
index++;
}
for (; j < nums2length; j++) {
r[index] = nums2[j];
index++;
}
int mi = r.length / 2;
return r.length % 2 == 1 ? r[mi] : (r[mi - 1] + r[mi]) / 2.0;
}
}
官方题解的代码:
class Solution {
public double findMedianSortedArrays(int[] A, int[] B) {
int m = A.length;
int n = B.length;
if (m > n) { // to ensure m<=n
int[] temp = A; A = B; B = temp;
int tmp = m; m = n; n = tmp;
}
int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
while (iMin <= iMax) {
int i = (iMin + iMax) / 2;
int j = halfLen - i;
if (i < iMax && B[j-1] > A[i]){
iMin = i + 1; // i is too small
}
else if (i > iMin && A[i-1] > B[j]) {
iMax = i - 1; // i is too big
}
else { // i is perfect
int maxLeft = 0;
if (i == 0) { maxLeft = B[j-1]; }
else if (j == 0) { maxLeft = A[i-1]; }
else { maxLeft = Math.max(A[i-1], B[j-1]); }
if ( (m + n) % 2 == 1 ) { return maxLeft; }
int minRight = 0;
if (i == m) { minRight = B[j]; }
else if (j == n) { minRight = A[i]; }
else { minRight = Math.min(B[j], A[i]); }
return (maxLeft + minRight) / 2.0;
}
}
return 0.0;
}
}
2019年9月10日重置版本
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len = nums1.length + nums2.length;
int index = 0;
int index1 = 0;
int index2 = 0;
// 偶数的话,取出中间两个数求平均
int pre = Integer.MIN_VALUE;
int last = 0;
if ((len & 1) == 0) {
len = (len >> 1) - 1;
while (index1 < nums1.length && index2 < nums2.length) {
if (nums1[index1] < nums2[index2]) {
if (index == len) {
pre = nums1[index1];
index1++;
break;
}
index1++;
index++;
} else {
if (index == len) {
pre = nums2[index2];
index2++;
break;
}
index2++;
index++;
}
}
if (pre == Integer.MIN_VALUE) {
if (index1 >= nums1.length) {
while (index < len) {
index2++;
index++;
}
pre = nums2[index2];
index2++;
} else {
while (index < len) {
index1++;
index++;
}
pre = nums1[index1];
index1++;
}
}
if (index1 < nums1.length && index2 < nums2.length) {
last = Math.min(nums1[index1], nums2[index2]);
} else if (index1 >= nums1.length) {
last = nums2[index2];
} else {
last = nums1[index1];
}
return (last + pre) / 2.0;
} else {
// 奇数的话直接取出中间的数字即可
len = len >> 1;
while (index1 < nums1.length && index2 < nums2.length) {
if (nums1[index1] < nums2[index2]) {
if (index == len) {
pre = nums1[index1];
index1++;
break;
}
index1++;
index++;
} else {
if (index == len) {
pre = nums2[index2];
index2++;
break;
}
index2++;
index++;
}
}
if (pre == Integer.MIN_VALUE) {
if (index1 >= nums1.length) {
while (index < len) {
index2++;
index++;
}
pre = nums2[index2];
index2++;
} else {
while (index < len) {
index1++;
index++;
}
pre = nums1[index1];
index1++;
}
}
return pre;
}
}
大概写了五十分钟吧,还是对于边界的不熟悉
这次的效率
看看官方的二分法:
二分法解释
class Solution {
public double findMedianSortedArrays(int[] A, int[] B) {
int m = A.length;
int n = B.length;
if (m > n) {
return findMedianSortedArrays(B,A); // 保证 m <= n
}
int iMin = 0, iMax = m;
while (iMin <= iMax) {
int i = (iMin + iMax) / 2;
int j = (m + n + 1) / 2 - i;
if (j != 0 && i != m && B[j-1] > A[i]){ // i 需要增大
iMin = i + 1;
}
else if (i != 0 && j != n && A[i-1] > B[j]) { // i 需要减小
iMax = i - 1;
}
else { // 达到要求,并且将边界条件列出来单独考虑
int maxLeft = 0;
if (i == 0) { maxLeft = B[j-1]; }
else if (j == 0) { maxLeft = A[i-1]; }
else { maxLeft = Math.max(A[i-1], B[j-1]); }
if ( (m + n) % 2 == 1 ) { return maxLeft; } // 奇数的话不需要考虑右半部分
int minRight = 0;
if (i == m) { minRight = B[j]; }
else if (j == n) { minRight = A[i]; }
else { minRight = Math.min(B[j], A[i]); }
return (maxLeft + minRight) / 2.0; //如果是偶数的话返回结果
}
}
return 0.0;
}
}