4 median-of-two-sorted-arrays

第四题评级是hard,看似很简单的题目着实没有那么容易做,主要原因在于时间复杂度的要求非常严格,基本上数组的题目,只要已经拍好了顺序,就必须在logN的复杂度下解决,当然后台的检测没有那么严格,O(n)也能通过,而为了而实现logN的复杂度,我也是在网上看了好久的答案,自己手推了一遍,才AC掉。

答题的思路是这样的:

1、两个有序数组,总共有多少个数已知,这道题的本质就变成了第K个小数是哪个的问题。

2、因为本题要求中位数,奇数和偶数个数之间是不同的,所以,如果是偶数个数字,需要求出第K/2个和第K/2+1个两个数。

3、假设有我现在有一个函数能求出来第K个数字,则主题函数的部分因该是这样的:

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int numsize1 = nums1.size();
        int numsize2 = nums2.size();
        double median = 0;
        
        vector<int> num1t = nums1;
        vector<int> num2t = nums2;
        median = findKthnum(num1t,num2t, (numsize1+numsize2)/2+1);
        if (!((numsize1 + numsize2)&0x1)){
            num1t = nums1;
            num2t = nums2;
            median += findKthnum(nums1, nums2, (numsize1+numsize2)/2);
            median = median/2;
        }
        return median;
    }

至于说findKthnum这个函数如何实现,我们现在先不用管,至少目前我们思路上很清楚,知道数据总长度,然后针对总长度是奇数和偶数两种情况,分别计算。整个函数的复杂度也就取决于findKthnum这个函数。

<1> 、我们可以在纸上画出一种比较理想的情况,就是两个数组各自的中位数是一模一样的,如果出现那样的情况,该数就是中位数,因为在该数两边,比其小的和比其大的数目一样。

<2>、假设nums1的中位数是m1,nums2的中位数是m2,如果m1比m2小,那么这两个数组的中位数就在m1和m2中间,m1<m<m2。

<3>、我们说这道题的本质是求第K小的数是多少,那是不是把前面K-1个数舍弃,剩下的数中第一个就是我们的目标数值。结合<2>中的说法,我们知道第K小的数在m1到m2之间,那m1之前的数是不是就可以舍弃了,那是肯定的,此后每次都是做这样的操作,每次都是将中位数小的数组剩余所有元素中的一半舍弃,所以时间复杂度是logN,最终舍弃K-1个元素即可。

以下是代码,其中要考虑较短数组剩余长度和总长度一半的比较,防止越界。
 

    int findKthnum (vector<int>& nums1, vector<int>& nums2, int k) {
        if (nums1.size() > nums2.size()) {
            return findKthnum (nums2, nums1, k);
        }
        if (nums1.size() < 1) {
            return nums2[k-nums1.size()-1];
        }
        if (k==1) {
            return min(nums1[0], nums2[0]);
        }
        int smsize1 = nums1.size();
        smsize1 = min(k/2, smsize1); int smsize2 = k-smsize1;
        if (nums1[smsize1-1] > nums2[smsize2-1]) {
            nums2.erase(nums2.begin(), nums2.begin()+smsize2);
            return findKthnum (nums1, nums2, k-smsize2);
        } else if (nums1[smsize1-1] < nums2[smsize2-1]) {
            nums1.erase(nums1.begin(), nums1.begin()+smsize1);
            return findKthnum (nums1, nums2, k-smsize1);
        } else {
            return nums1[smsize1-1];
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_29592167/article/details/83061553