zoukankan      html  css  js  c++  java
  • LeetCode 4 Median of Two Sorted Arrays 查找中位数,排除法,问题拓展 难度:1

    思路:设现在可用区间在nums1是[s1,t1),nums2:[s2,t2)

    1.当一个数组可用区间为0的时候,由于另一个数组是已经排过序的,所以直接可得

    当要取的是最小值或最大值时,也直接可得

    2.明显两个数组总长度为偶数的时候需要取最中间两个元素/2.0,长度为奇数时,只需要求最中间那个.所以只需要分别求出最多两个元素,分别是

    (findKthElement(0,t1,0,t2,(t1 + t2)/2) 和 findKthElement(0,t1,0,t2,(t1 + t2)/2 + 1)

    (这一步没有想到可以抛弃中位数,直接转化为求第k大的数,导致第一版代码非常难看.)

    在这里我们把这个问题拓展为在两个数组中求第k大的数

    3.

    下面来看一个例子

    在以上的nums1,nums2中求第7大数,要知道,去除了最小的六个数,剩下的可用区间中最小的数一定是第7大数,

    可是我们怎么知道哪些数才能够被去除呢?

    我们当然可以胡乱取个值,比如nums1[0],也就是8,我们发现它恰好比nums2[0]要小,这样一看,nums1[0]是最小的数字,可以去除,但这样效率太慢了.

    效率比较高的是哪个数字呢?比如7/2 = 3,

    这个时候nums1[2]>nums2[2],也就是说nums2[0-2]一定小于nums1[2],此时可能比它们中某些值大的数字只有3-1 = 2个,也即nums2[0-2]一定在前6个里,我们就可以舍弃nums2[0-2],现在问题转化为在nums1[3,5),nums2[0,4)中取第4小的那个数,怎么样,问题的数据规模是不是变得小了不少......

    也就是说,当在以上可用区间取第k大数的时候,设nums1[tmp1],nums2[tmp2]分别是从各自起点出发的第k/2个数(或者是小于第k/2且可取的最后一个数),那么假设nums1[tmp1]<nums2[tmp2],则明显[s1,tmp1]这个区间的都在第k个数之前,所以可以直接把它们去掉,反之可以舍弃[s2,tmp2](别忘了k里面也要划去舍弃部分的长度)

    class Solution
    {
    public:
        const int inf = ~0u >> 1;
        vector<int> nums1,nums2;
        double findKthElement(int s1,int t1,int s2,int t2,int k)
        {
           // assert(t1 - s1 + t2 - s2 >= k);
            if(s1 == t1)return nums2[s2 + k - 1];
            else if(s2 == t2)return nums1[s1 + k - 1];
            if(k == 1)return min(nums1[s1],nums2[s2]);
            if(k == t1 - s1 + t2 - s2)return max(nums1[t1 - 1],nums2[t2 - 1]);
            int tmp1 = min(s1 + k/2 - 1,t1 - 1);
            int tmp2 = min(s2 + k/2 - 1,t2 - 1);
            if(nums1[tmp1] < nums2[tmp2])
            {
                return findKthElement(tmp1 + 1,t1,s2,t2,k - tmp1 + s1 - 1);
            }
            else if(nums1[tmp1] > nums2[tmp2])
            {
                return findKthElement(s1,t1,tmp2 + 1,t2,k - tmp2 + s2 - 1);
            }
            else
            {
                if((k & 1) == 0)return nums2[tmp2];
                else return min((tmp1 + 1< t1?nums1[tmp1 + 1]:inf),
                                    (tmp2 + 1< t2?nums2[tmp2 + 1]:inf));
            }
        }
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
        {
            this->nums1 = nums1;
            this->nums2 = nums2;
            sort(nums1.begin(),nums1.end());
            sort(nums2.begin(),nums2.end());
            int t1 = nums1.size(),t2 = nums2.size();
            return ((t1 + t2) & 1) == 0?
                   (findKthElement(0,t1,0,t2,(t1 + t2)/2) + findKthElement(0,t1,0,t2,(t1 + t2)/2 + 1))/2.0
                   :findKthElement(0,t1,0,t2,(t1 + t2)/2 + 1);
        }
    };
    

      

  • 相关阅读:
    【Linux】PS命令
    【Linux】多进程与多线程之间的区别
    【杂项】XML Schema和DTD的区别
    推荐一组强大的Collection类
    关于Decorator模式我的理解
    菜鸟白话设计模式系列
    PowerCollections研究: 第1弹竟就发现不少问题
    [白话设计模式] Singleton
    PowerCollection研究:第2枪小谈RemoveALL算法
    yield 关键字
  • 原文地址:https://www.cnblogs.com/xuesu/p/4775457.html
Copyright © 2011-2022 走看看