zoukankan      html  css  js  c++  java
  • 【Leetcode】寻找两个有序数组的中位数

    使用二分法搜寻合适的i值,计算对应的j值,最后通过分类讨论nums1和nums2的多种情况计算得到中值。

    二分法的关键思想是   假设该数组的长度是N那么二分后是N/2,再二分后是N/4……直到二分到1结束(当然这是属于最坏的情况了,即每次找到的那个中点数都不是我们要找的),那么二分的次数就是基本语句执行的次数,于是我们可以设次数为x,N*(1/2)^x=1;则x=logn,底数是2。

    因此,该问题的时间复杂度是 O(log(min(m,n)).

    空间复杂度 O(m+n)

    执行用时 : 300ms, 在Median of Two Sorted Arrays的C++提交中击败了7.57% 的用户
    内存消耗 : 11 MB, 在Median of Two Sorted Arrays的C++提交中击败了77.28% 的用户
    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            double ans;
            int len1 = nums1.size();
            int len2 = nums2.size();
            if (len1 > len2){
                vector<int> temp(nums1);
                nums1 = nums2;
                nums2 = temp;
                len1 = nums1.size();
                len2 = nums2.size();
            }
            
            // if nums1 is empty 
            if (len1 == 0){
                if (len2 % 2 == 0)
                    return ans = 0.5*(nums2[len2/2 - 1] + nums2[len2/2]);
                else
                    return ans = nums2[int(len2/2)];
            }
            
            int i = 0, j = 0;
            int imin = 0, imax = len1; // 这两个变量用于二分法
            
            while(imin <= imax){  // 二分法的开展条件
                i = int(0.5*(imin+imax));
                j = getValueJ(len1,len2,i);
                
                if(i==0 || j==len2 || nums1[i-1] <= nums2[j]){
                    if(i==len1 || j==0 || nums1[i] >= nums2[j-1]){
                        ans = getMedian(nums1, nums2, len1, len2, i, j);
                        break;
                    }
                    else{
                        imin = i+1;
                        cout << "imin : " << imin << endl;
                    }
                }
                else{
                    imax = i;
                }
            }
            return ans;
        }
        
        int getValueJ(int len1, int len2, int iIndex){
            int jIndex;
            if ((len1+len2) % 2 == 0)
                jIndex = 0.5*(len1+len2) - iIndex;
            else
                jIndex = 0.5*(len1+len2+1) - iIndex;
            
            return jIndex;
        }
        
        double getMedian(vector<int> &num1, vector<int> &num2, int len1, int len2, int iIndex, int jIndex){
            
            /*********
            for (int i = 0; i < len1; i++)
                cout << num1[i] << " ";
            cout << endl;
            for (int j = 0; j < len2; j++)
                cout << num2[j] << " ";
            cout << endl;
            
            cout << "iIndex : "<< iIndex << endl;
            cout << "jIndex : "<< jIndex << endl;
            
            cout << "len1 : " << len1 << endl;
            cout << "len2 : " << len2 << endl;
            **********/        
    
            double median;
            vector<int> leftP, rightP;
            
            if ((len1+len2) % 2 ){
                cout << "the sum of two vector is odd number" << endl;
                
                // we know that size of vector leftP is bigger than that of vector rightP
                if (iIndex > 0 && jIndex > 0){
                    vector<int> tmp;
                    for (int i = 0; i < iIndex; i++)
                        tmp.push_back(num1[i]);
                    for (int j = 0; j < jIndex; j++)
                        tmp.push_back(num2[j]);
                    median =  *max_element(tmp.begin(), tmp.end());
                }
                else if (iIndex == 0)
                    median = *max_element(num2.begin(), (num2.end()-(len2-jIndex)));
                else if (jIndex == 0)
                    median = *max_element(num1.begin(), (num1.end()-(len1-iIndex)));
    
            }
            
            else{
                cout << "the sum of two vector is even number" << endl;
                
                if (iIndex == 0){
                    leftP.clear();
                    rightP.clear();
                    for (int j = 0; j < jIndex; j++){
                        leftP.push_back(num2[j]);
                    }
                    
                    rightP = num1;
                    if(jIndex < len2)
                        for(int j = jIndex; j < len2; j++)
                            rightP.push_back(num2[j]);
                    
                    /**************
                    cout << "leftP : ";
                    for(int i = 0; i < leftP.size(); i++)
                        cout << leftP[i] << " ";
                    cout << endl << "rightP : ";
                    for(int j = 0; j < rightP.size(); j++)
                        cout << rightP[j] << "";
                    cout << endl;
                    **************/
                }
                
                else if (iIndex == len1){
                    leftP.clear();
                    rightP.clear();
                    leftP = num1;
                    if (jIndex > 0 && jIndex < len2)
                        for (int j = 0; j < jIndex; j++)
                            leftP.push_back(num2[j]);
                    
                    for (int j = jIndex; j < len2; j++)
                        rightP.push_back(num2[j]);
                }
                
                else{
                    leftP.clear();
                    rightP.clear();
                    for (int i = 0; i < iIndex; i++)
                        leftP.push_back(num1[i]);
                    
                    if(jIndex > 0){
                        for(int j = 0; j < jIndex; j++)
                            leftP.push_back(num2[j]);
                    }
                    
                    for(int i = iIndex; i < len1; i++)
                        rightP.push_back(num1[i]);
                    
                    if(jIndex < len2)
                        for(int j = jIndex; j < len2; j++)
                            rightP.push_back(num2[j]);
                }
                
                int leftV =  *max_element(leftP.begin(), leftP.end());
                int rightV = *min_element(rightP.begin(), rightP.end());
                cout << "leftV : " << leftV << "  " << "rightV : " << rightV << endl;
                median = 0.5*(leftV+rightV);                        
            }
            return median;
        }
    };

    nums1和nums2都是按升序排列,其长度size = m+n。将前 size/2+1(size为偶数) 或 (size+1)/2(size为奇数) 进行排序,即可找到中位数。

    Tip: 学习迭代器的使用,迭代器的增长;

    执行用时 : 32 ms, 在Median of Two Sorted Arrays的C++提交中击败了98.57% 的用户
    内存消耗 : 9.7 MB, 在Median of Two Sorted Arrays的C++提交中击败了87.28% 的用户
    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            
            auto left = nums1.begin();
            auto right = nums2.begin();
            int size = nums1.size() + nums2.size();
            //int sum = 0;
            int temp = 0; 
            int temp1 = 0;
            for (int i = 0; i <= size / 2; i++)
            {    
                if (left == nums1.end())
                    temp = *right++;
                else if (right == nums2.end())
                    temp = *left++;
                else if (*left < *right)
                    temp = *left++;
                else
                    temp = *right++;
                if (size / 2 - 1 == i)
                {
                    temp1 = temp;
                }
            }
            if (size % 2 != 0)
            {
                return temp;
            }
            else
            {
                return (temp + temp1) / 2.0;
            }
    
        }
    };
  • 相关阅读:
    (dp)LeetCode Weekly Contest 34 -Non-negative Integers without Consecutive Ones
    (后缀数组)poj 3581 Sequence
    (最小生成树)Codeforces 76 A Gift
    (最小生成树)Codeforces Educational Codeforces Round 9 Magic Matrix
    (AC自动机)UVALive
    (trie)BUAAOJ 371
    CCF 201312-3 最大的矩形
    http错误代码含义
    数据结构-5-二叉树的实现以及递归遍历的实现
    数据结构-3.4-栈与队列
  • 原文地址:https://www.cnblogs.com/gdut-gordon/p/10803868.html
Copyright © 2011-2022 走看看