力扣刷题:4. 寻找两个正序数组的中位数

题目要求

给定两个大小为 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;
分母变成浮点数,除法自动转换为浮点数除法。

猜你喜欢

转载自blog.csdn.net/youyadefeng1/article/details/113403102