zoukankan      html  css  js  c++  java
  • leecode4:寻找两个正序数组的中位数

    1.题目描述

    给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

    2.示例

    示例 1:

    输入:nums1 = [1,3], nums2 = [2]
    输出:2.00000
    解释:合并数组 = [1,2,3] ,中位数 2

    示例 2:

    输入:nums1 = [0,0], nums2 = [0,0]
    输出:0.00000

    示例 3:

     输入:nums1 = [1,2], nums2 = [3,4]
     输出:2.50000
     解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

    3.分析

    此题难度不大,有如下思路

    (1)最简单的想法是,将一个数组的每一个元素,按照升序通过插入法等方法将两个数组合并。然后根据奇偶性质找出中位数的位置并计算。

    但是这种方法不是高效的,空间上它需要重新申请一个m+n长度的新数组。至少也需要将较短的那个数组重新申请空间到较长的那个数组上。

    时间上,由于每次需要将一个元素有序插入到另一个数组中,时间也会有较大的浪费。

    (2)根据上面的方法,时间浪费的原因在于没有利用好两个数组已经有序的条件。改进的方法,不再将两个数组和并,也不关心中位数之后的元素

    的排序。通过两个数组的元素和计算出中位数的位置,设置指向两个数组的两个游标进行移动。在两个数组的元素都没被遍历完时,比较当前两个游标对应的元素大小,使较小元素的游标后移。

    在某一个数组已经被比较完时,则将另一个数组的元素顺序不动遍历即可,直到整体的游标数到达中位数的位置。

    这样就提高了时间和空间的效率,类似流的不保存元素的值,只关心中位数的位置。达到了空间复杂度为O(m+n)

    4.代码

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int total = nums1.size() + nums2.size();//总元素数
            int numPos1 = 0;//数组1的游标
            int numPos2 = 0;//数组2的游标
            int counter = 0;//计数器
            float result =0;//结果值
    
            if(total%2!=0){//奇数
                while(counter<total/2){
                    if(numPos1<nums1.size()&&numPos2<nums2.size()){
                        if(nums1.at(numPos1)<nums2.at(numPos2))   numPos1++;
                        else    numPos2++;
                    }
                    else if(numPos1<nums1.size())  numPos1++;
                    else    numPos2++;
                    counter++;
                }
                if(numPos1<nums1.size()&&numPos2<nums2.size()){
                        if(nums1.at(numPos1)<nums2.at(numPos2))   result+=nums1.at(numPos1);
                        else    result+=nums2.at(numPos2);
                    }
                    else if(numPos1<nums1.size())  result+=nums1.at(numPos1);
                    else    result+=nums2.at(numPos2);
    
            }else{//偶数
                while(counter<total/2-1){
                    if(numPos1<nums1.size()&&numPos2<nums2.size()){
                        if(nums1.at(numPos1)<nums2.at(numPos2))   numPos1++;
                        else    numPos2++;
                    }
                    else if(numPos1<nums1.size())  numPos1++;
                    else    numPos2++;
                    counter++;
                }
                for(int i=0;i<2;i++){
                    if(numPos1<nums1.size()&&numPos2<nums2.size()){
                        if(nums1.at(numPos1)<nums2.at(numPos2))   {result+=nums1.at(numPos1);numPos1++;}
                        else    {result+=nums2.at(numPos2);numPos2++;}
                    }
                    else if(numPos1<nums1.size())  {result+=nums1.at(numPos1);numPos1++;}
                    else    {result+=nums2.at(numPos2);numPos2++;}
                }
                result =result/2;
            }
            return result;
        }
    };

    5.总结

    (1)上述代码不够优雅,原因是一开始就将奇偶分开处理,导致有很大程度的重复代码。

    (2)这也说明了这个题的细节问题:即对奇偶元素个数的游标位置的处理细节。

    
    
  • 相关阅读:
    [转]Nvidia 的Shadow 文章收集
    [转]Linear Depth Buffer(线性深度缓冲区)
    [转]ParallelSplit Shadow Maps on Programmable GPUs
    [转]Learning to Love your Zbuffer.
    SQL SERVER存储过程中使用事务
    VS2005+SQL2005 Reporting Service动态绑定报表(Web)
    Sql批量删除/插入
    存储过程中执行动态Sql语句
    存储过程中使用事务
    真正的全动态报表:RDLC+ReportViewer
  • 原文地址:https://www.cnblogs.com/fangexuxiehuihuang/p/14504809.html
Copyright © 2011-2022 走看看