Liqueu: 4. Find the median of two positive-order arrays

Subject requirements

Given two positive-order (from small to large) arrays of size m and n, nums1 and nums2. Please find and return the median of these two positive-order arrays.

Advanced: Can you design an algorithm with a time complexity of O(log (m+n)) to solve this problem?
Insert picture description here
Topic link

Version 1: Call library functions directly

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;
        }
    }
};

(This version does not meet the requirements of the investigation and requires manual implementation of lower-level operations)

What learned

1. Familiar with the usage of the generic algorithm sort: pass in two iterators, and then the algorithm will
sort the numbers in the iterator range according to the default < 2. Sort is defined in the header file algorithm
3. Familiar with the generic algorithm Usage of copy: Pass in two iterators and a starting position iterator. Copies the numbers in the specified range of the first two iterators to the position starting with the third iterator. By default, the third position has sufficient space.

Version 2: Start from the bottom

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++];
        }
    }
};

Learned what

1. Learn to write a merge sort by yourself. The merge sort is mainly divided into two parts, divide and conquer. In this question, "division" is implemented by the mysort function, which calls the mysort function twice, once to sort the left sequence, and once to sort the right sequence.
The division here does not divide the data in the container on the physical memory, but passes different left and right boundaries through a recursive function to achieve logical recursion.

"Treatment" is achieved through the mymerge function. After calling the mysort function twice, the left and right sides are sorted, and then the mymerge function is called.
After the logical division, the left, mid, and right passed in are used to define the left and right boundaries. The incoming container reference can change the actual physical storage data. The incoming temp container reference is to avoid frequent opening up of space in recursion.

Reference article

2. Regarding the division of int and double, int
return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2;
is returned, and the decimal part is truncated. Here is a pit

return (nums1[nums1.size() / 2] + nums1[(nums1.size() / 2) - 1]) / 2.0;
The denominator becomes a floating point number, and the division is automatically converted to a floating point number division.

Guess you like

Origin blog.csdn.net/youyadefeng1/article/details/113403102