There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
版本一(自己写的,未经优化):
分别用n-1、m-1代表两个列表的尾,j、k代表两个列表的头。
两个列表先后面向前比较,大的丢掉,即n或者m减一。然后前面向后比较,小的丢掉,即j或者k加一
此时也要考虑n减一和j加一是否重叠,即该数组“去掉”所有数为空了,(m,k同理),然后简化为一列数组,直接用函数找出中位数
再考虑两个数组同时留下一个数的情况
#include<stdio.h>
#include<vector>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(), m = nums2.size();
int j = 0, k = 0;
if (n == 0)
return findMedian(nums2, 0, m - 1);
else if (m == 0)
return findMedian(nums1, 0, n - 1);
while (n + m > 2) {
if (nums1[n - 1] > nums2[m - 1]) {
if (n - j - 1 == 0) {
if (nums2[k] < nums1[n - 1])
return findMedian(nums2, k + 2, m - 2);
return findMedian(nums2, k, m - 1);
}
n--;
}
else {
if (m - k - 1 == 0) {
if (nums1[j] < nums2[m - 1])
return findMedian(nums1, j + 2, n - 2);
return findMedian(nums1, j, n - 1);
}
m--;
}
if (nums1[j] <= nums2[k]) {
j++;
if (j == n)
return findMedian(nums2, k, m - 1);
}
else {
k++;
if (k == m)
return findMedian(nums1, j, n - 1);
}
if (n - j == 1 and m - k == 1) {
return (nums1[j] + nums2[k]) / 2.0;
}
}
return (nums1[n - 1] + nums2[m - 1]) / 2.0;
}
double findMedian(vector<int>& list, int head, int end) {
if (head == end)
return list[head];
int mid = (head + end) / 2;
int size = end - head + 1;
if (size % 2 == 0)
return (list[mid] + list[mid + 1]) / 2.0;
else
return list[mid];
}
};
int main() {
vector<int> nums1{ 5 };
vector<int> nums2{ 1,2,3 ,4 };
printf("%lf", Solution().findMedianSortedArrays(nums1, nums2));
return 0;
}
版本二(有个实例没通过,待思考):
分别计算两个序列的中位数M1和M2,假设M1>M2,那么数列中比M2大的和比M1小的保留,并且统计去掉“大”(即比M1大)的数的个数和“小”的数的个数,若不相等,个数少的一方需要继续去掉。比如说去掉了3个“大”数,和2个“小”数,那么就需要再去掉一个“小”的数,以达到平衡。
重复上面步骤,直到M1=M2或者只剩下两个数,分别做相应处理即可。
不通过案例[1,2] [-1,3]。它们的中位数是1.5和1,去掉比1小,比1.5大的数,剩下[1] [ ],“大”数去掉了2个,“小”数去掉了1个,需要再去掉一个“小”数,于是剩下[ ] [ ]。出现错误。
可以考虑分情况,如果是序列个数是偶数,则最少保留两个,奇数则最少保留一个,待检验吧
#include<stdio.h>
#include<vector>
#include<math.h>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(), m = nums2.size();
int h1 = 0, h2 = 0, b1 = n - 1, b2 = m - 1;
if (n == 0)
return Median(nums2, h2, b2);
else if (m == 0)
return Median(nums1, h1, b1);
printlist(nums1, h1, b1);
printlist(nums2, h2, b2);
while (true) {
int big = 0, small = 0;
double m1 = Median(nums1, h1, b1);
double m2 = Median(nums2, h2, b2);
printf("\nm1:%f m2:%f\n", m1, m2);
if (m1 == m2)
return m1;
if (m1 > m2) {
h1 = del(nums1, m2, h1, b1);
h2 = del(nums2, m2, h2, b2);
b1 = del(nums1, m1, h1, b1, 1);
b2 = del(nums2, m1, h2, b2, 1);
}
else {
h1 = del(nums1, m1, h1, b1);
h2 = del(nums2, m1, h2, b2);
b1 = del(nums1, m2, h1, b1, 1);
b2 = del(nums2, m2, h2, b2, 1);
}
small = h1 + h2;
big = n + m - b1 - b2 - 2;
printf("small: %d,big: %d\n", small, big);
//printf("h1: %d,b1: %d\n", h1, b1);
printlist(nums1, h1, b1);
//printf("h2: %d,b2: %d\n", h2, b2);
printlist(nums2, h2, b2);
if (small == big)
return (nums1[h1] + nums2[h2]) / 2.0;
else if (small > big) {
for (int i = small - big; i > 0; i--) {
if (nums1[b1] > nums2[b2]) {
if (h1 - b1 == 0)
return Median(nums2, h2, b2 - i + 1);
b1--;
}
else {
if (h2 - b2 == 0)
return Median(nums1, h1, b1 - i + 1);
b2--;
}
}
}
else {
for (int i = big - small; i > 0; i--) {
if (nums1[h1] > nums2[h2]) {
if (b2 - h2 == 0)
return Median(nums1, h1 + i - 1, b1);
h2++;
}
else {
if (b1 - h1 == 0)
return Median(nums2, h2 + i - 1, b2);
h1++;
}
}
}
}
}
double Median(vector<int>& list, int head, int end) {
if (head == end)
return list[head];
int mid = (head + end) / 2;
int size = end - head + 1;
if (size % 2 == 0)
return (list[mid] + list[mid + 1]) / 2.0;
return list[mid];
}
int del(vector<int>& list, double m, int head, int end, int j = 0) {
int mid = (head + end) / 2;
printf("list[mid]: %d m:%f\n", list[mid], m);
if (j) {
if (list[mid] < m) {
while (end >= mid + 1 && list[mid] < m && list[mid + 1] <= m) {
mid++;
}
}
else if (mid - 1 >= 0)
mid--;
}
else {
if (list[mid] >= m) {
while (mid - 1 >= 0 && list[mid] >= m && list[mid - 1] >= m) {
mid--;
}
}
else if (mid - 1 <= end)
mid++;
}
return mid;
}
void printlist(vector<int>& list, int head, int end) {
printf("head:%d end:%d\nlist:", head, end);
for (int i = head; i <= end; i++)
printf("%d ", list[i]);
printf("\n");
}
};
int main() {
vector<int> nums1{ 1,2 };
vector<int> nums2{ -1,3 };
printf("%lf", Solution().findMedianSortedArrays(nums1, nums2));
return 0;
}