题目要求
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。
进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
题目链接
版本一:直接调用库函数
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
auto backInsert = std::back_inserter(nums1);
std::copy(nums2.cbegin(), nums2.cend(), backInsert);
std::sort(nums1.begin(), nums1.end());
if (nums1.size() % 2 == 1)
{
return nums1[nums1.size() / 2];
}
else
{
return (nums1[nums1.size() / 2] + nums1[nums1.size() / 2 - 1]) / 2.0;
}
}
};
(这个版本不符合考察要求,需要手工实现更加底层的操作)
学到了什么
1、熟悉了泛型算法sort的用法:传入两个迭代器,然后该算法会对迭代器范围内的数按照默认<进行排序
2、sort定义在头文件algorithm里面
3、熟悉了泛型算法copy的用法:传入两个迭代器和一个起始位置迭代器。将前两个迭代器指定范围内的数拷贝到以第三个迭代器起始的位置。默认第三个位置空间充足。
版本二:从底层做起
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
for (auto i : nums2)
nums1.push_back(i);
vector<int> temp(nums1.size(), 0);
mysort(nums1, 0, nums1.size() - 1, temp);
if (nums1.size() % 2 != 0)
{
return nums1[nums1.size() / 2];
}
else
{
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2.0;
}
}
void mysort(vector<int>& v, unsigned left, unsigned right, vector<int>& temp)
{
if (left < right)
{
unsigned mid = (left + right) / 2;
mysort(v, left, mid, temp);
mysort(v, mid + 1, right, temp);
mymerge(v, left, mid, right, temp);
}
}
void mymerge(vector<int>& v, unsigned left, unsigned mid, unsigned right, vector<int>& temp)
{
unsigned l = left, r = mid+1, t = 0;
while (l <= mid && r <= right)
{
if (v[l] <= v[r])
{
temp[t++] = v[l++];
}
else
{
temp[t++] = v[r++];
}
}
while (l <= mid)
{
temp[t++] = v[l++];
}
while (r <= right)
{
temp[t++] = v[r++];
}
t = 0;
while (left <= right)
{
v[left++] = temp[t++];
}
}
};
学会了什么
1、学会了自己写一个归并排序。归并排序主要分为两部分,分和治。本题中,“分”通过mysort函数实现,递归调用了两次mysort函数,一次排序左边序列,一次排序右边序列。
这里的分并没有在物理内存上将容器中的数据进行切分,而是通过递归函数传递不同的left和right边界实现逻辑上的递归。
“治”通过mymerge函数实现,在调用完两次mysort函数,将左右两边都排好序后,调用mymerge函数。
在逻辑上切分好后,便通过传递进来的left、mid、right界定左右两个界限。传入的容器引用可以实现实际上物理存储数据的改变。而传入的temp容器引用则是为了避免递归中频繁开辟空间。
2、关于int和double进行除法的问题
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2;
返回的是int,小数部分被截断了,这里踩了一次坑
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2.0;
分母变成浮点数,除法自动转换为浮点数除法。