4. 寻找两个有序数组的中位数

好久没有刷过题了,刚好最近刷了几道,然后也复习下vector的用法.

题目是给了两个数组,然后求中位数,可以看成是求最K小的数,如果时间上没有要求的话,可以用暴力遍历就行。

因为已知数组是排好序的,所以只需要将两个数组的进行O(max(n,m))的遍历,然后根据数组长度的奇偶性,输出中位数,然后样例是doube类型,输出的时候要强转。这种方法要格外申请数组,所以内存上还是有消耗的。

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

还有另外一种可以根据折半的查找,类似于二分吧~

主要是分两种情况,

数组A和B,首先将数组折半,中位数分别是m1,m2,下标分别是i1,i2

然后

如果 i1 + i2 < k

  如果m1 > m2,那么中位数不在B数组的前半段,则此时需要更新求第K = K - i2 - 1小的数;

  如果m1 <= m2,那么同理中位数不在A数组的前半段,则此时需要更新求K = K - i1 - 1小的数;

如果 i1 + i2 >= k

  如果m1 > m2,那么中位数不在A数组的后半段,继续求第K小的数;

  如果m1 <= m2,那么中位数不在B数组的后半段,继续求第K小的数;

 

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size() + nums2.size();
        vector<int> aa(nums1.begin(),nums1.begin() + nums1.size());
        vector<int> bb(nums2.begin(),nums2.begin() + nums2.size());
        if(n%2 == 1){
            return findk(nums1,nums2,n/2);
        }
        else{
            return (findk(nums1,nums2,n/2) + findk(aa,bb,n/2-1) )/ 2.0;
        }
       
    }
    double findk(vector<int>& nums1,vector<int>& nums2,int k){
        if(nums1.size() == 0){
            return nums2[k];
        }
        if(nums2.size() == 0){
            return nums1[k];
        }
        int n = nums1.size();
        int m = nums2.size();
        int i1 = n/2;
        int i2 = m/2;
        int m1 = nums1[i1];
        int m2 = nums2[i2];
        if(i1 + i2 < k){
            if(m1>m2){
                nums2.erase(nums2.begin(),nums2.begin()+i2 + 1);
                return findk(nums1,nums2,k-i2-1);
            }
            else{
                nums1.erase(nums1.begin(),nums1.begin() + i1 + 1);
                return findk(nums1,nums2,k-i1-1);
            }
        }
        else{
            if(m1>m2){
                int tx = i1;
                if(i1 == 0 && nums1.size() == 1) tx = i1 + 1;
                while(tx > 0 && nums1.size() !=0){
                    nums1.pop_back();
                    tx--;
                }
                return findk(nums1,nums2,k);
            }
            else{
                int tx = i2;
                if(i2 ==0 && nums2.size() == 1) tx = i2 + 1;
                while(tx > 0 && nums2.size() != 0){
                 
                    nums2.pop_back();
                    tx--;
                }
      
                return findk(nums1,nums2,k);
            }
        }
        return 0.0;
    }
};

写代码的时候再vector.erase的时候,一直用的是

ums2.erase(nums2.end()-i2,nums2.end());

然后如果当数组i2=0,然后nums2.size == 1 的时候,会不能清空,会进入死循环。

priority_queue<int ,vector<int >,less<int> >que; //从大到小排列
priority_queue<int ,vector<int >,greater<int> >que;//从小到大排列

顺便记下优先队列,之前写广搜经常用到,现在好久没有刷题了,都不记得了。。。。

posted on 2020-05-05 23:29  `Elaine  阅读(183)  评论(0编辑  收藏  举报

导航