• [LeetCode]4. Median of Two Sorted Arrays两个排序数组合并后的中位数


    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)).

    解法一:不考虑时间复杂度限制在O(log(m+n)),则将两个数组遍历一遍即可以组合成一个排好序的数组,然后取数组的中位数即可,时间复杂度O(m+n):

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int m = nums1.size();
            int n = nums2.size();
            vector<int> vi(m + n, 0);
            int i = 0;
            int j = 0;
            int k = 0;
            
            if(m == 0)
            {
                if(n == 0)
                    return 0;
                else
                    return (n % 2 == 0) ? (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0 : nums2[n / 2];
            }
            if(n == 0)
            {
                if(m == 0)
                    return 0;
                else
                    return (m % 2 == 0) ? (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0 : nums1[m / 2];
            }
            
            if(m + n == 1)
                return (m == 1) ? nums1[0] : nums2[0];
            
            for(int i = 0; i < m;)
            {
                if(j < n && nums1[i] > nums2[j])
                {
                    vi[k] = nums2[j];
                    j++;
                    k++;
                }
                else
                {
                    vi[k] = nums1[i];
                    i++;
                    k++;
                }
            }
            while(j < n)
            {
                vi[k] = nums2[j];
                j++;
                k++;
            }
            
            if((m + n) % 2 == 0)
                return (vi[(m + n) / 2 - 1] + vi[(m + n) / 2]) / 2.0;
            else
                return vi[(m + n) / 2];
        }
    };

    解法二:考虑时间复杂度要在O(log(m+n)),则不能简单的从头至尾遍历两个数组。因为数组都是排序的,一种自然地想法即是考虑二分查找。找到两个排序数组的中位数的一个延伸问题是找到两个排序数组的第K大元素,中位数是K=(m+n)/2的情况。可以这样考虑:先分别找到两个排序数组的第K大元素进行比较,即比较arr1[k/2-1]和arr2[k/2-1]的大小,假设arr1[k/2-1]>arr2[k/2-1],则显而易见arr2中排在arr2[k/2-1]之前的元素不可能是合并后排序数组的中位数,因为arr2[k/2-1]不可能大于合并后数组的第K大值,而arr2[0]到arr2[k/2-2]均小于arr2[k/2-1],则更不可能是合并后数组的第K大值了,因此这部分可以丢弃;然后再对一个旧的排序数组和一个新的排序数组递归调用上述过程,最后即可得到合并后排序数组的第K个数。

    需要注意的是需要针对数组长度小于K/2的情况单独考虑。

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int m = nums1.size();
            int n = nums2.size();
            int t = m + n;
    
            if (m == 0 || n == 0)
            {
                if (m == 0 && n == 0)
                    return -1;
                if (m == 0 && n > 1)
                {
                    if (n % 2 == 0)
                        return (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0;
                    else
                        return nums2[n / 2];
                }
                if (n == 0 && m > 1)
                {
                    if (m % 2 == 0)
                        return (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0;
                    else
                        return nums1[m / 2];
                }
            }
            if (t == 1)
                return (m == 0) ? nums2[0] : nums1[0];
            if (t == 2)
                return (nums1[0] + nums2[0]) / 2.0;
    
            if (t % 2 == 0)
                return (findKth(nums1, m, nums2, n, t / 2) + findKth(nums1, m, nums2, n, t / 2 + 1)) / 2.0;
            else
                return findKth(nums1, m, nums2, n, t / 2 + 1);
        }
    private:
        double findKth(vector<int> a, int as, vector<int> b, int bs, int k)
        {
            if (as > bs)
                return findKth(b, bs, a, as, k);
    
            if (k <= 0)
                return -1;
            if (as == 0 || bs == 0)
            {
                if (as == 0 && bs == 0)
                    return -1;
                if (as == 0)
                    return b[k - 1];
                if (bs == 0)
                    return a[k - 1];
            }
            if (k == 1)
                return a[0] > b[0] ? b[0] : a[0];
    
            int pa = k / 2 > as ? as : k / 2;
            int pb = k - pa;
            if (a[pa - 1] > b[pb - 1])
                return findKth(a, as, vector<int>(b.begin() + pb, b.end()), bs - pb, k - pb);
            else if (a[pa - 1] < b[pb - 1])
                return findKth(vector<int>(a.begin() + pa, a.end()), as - pa, b, bs, k - pa);
            else
                return a[pa - 1];
        }
    };
  • 相关阅读:
    jquery的data、attr、expando
    Vue-router导航问题
    函数声明与函数表达式
    Object.defineProperty方法
    移动端Web开发,ios下 input为圆角
    parseInt和map方法使用案例分析
    字符串处理常见函数
    ES6之Promise的基本用法
    浮动相关
    知识点拾遗
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/4840669.html
Copyright © 2020-2023  润新知