ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode/寻找两个正序数组中位数

2022-06-17 23:00:35  阅读:145  来源: 互联网

标签:正序 int start1 中位数 nums1 start2 vector LeetCode nums2


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

1. 辅助空间暴力法

将两数组合并,分奇偶取中位数

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        vector<int> merge;
        int i =0; int j=0;
        while(i<m&&j<n){
            if(nums1[i]<=nums2[j]){ merge.push_back(nums1[i]); i++;}
            else {merge.push_back(nums2[j]); j++;}
        }
        while(i<m){merge.push_back(nums1[i]); i++;}
        while(j<n){merge.push_back(nums2[j]); j++;}
        if((m+n)%2==0) return (merge[(m+n)/2-1]+ merge[(m+n)/2])/2.0;
        else return merge[(m+n)/2];
    }
};

2. 双指针暴力法

不需要辅助空间,让两指针边比较边移动,到中间位置即可,分奇偶输出结果
这里不要单纯记录指针,单纯记录指针的话,最后获得结果的时候,既要讨论是否为空集
又要讨论两指针哪个数为后一个数,以及求在偶数的情况下前一个数的位置,非常麻烦
干脆每次遍历都记录更新两个对应值,最后直接得到中位数

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int len = m+n;
        int left =-1; int right=-1;//记录中位数值,避免单纯记录指针的分类讨论,避免处理一数组为空集
        int start1 = 0; int start2 = 0;//两指针初始位置
        for(int i=0;i<=len/2;i++){//直接遍历len/2 + 1次 ,不用指针进行跳出,避免分类讨论
            left = right;
            //处理边界条件和移动条件
            if(start1 < m && (start2 >= n || nums1[start1] < nums2[start2]))
                {right = nums1[start1]; start1++;}
            else  {right = nums2[start2]; start2++;}
        }
        if(len%2==0) return (left + right) / 2.0;
        else return right;
    }
};

3. 二分法

因为已经是有序的,合理使用二分性能最好
关键在于如何通过二分使问题规模变小,容易判断通过取两数组中间位置进行比较
可以排除掉较小数前面所有数,但对剩下的数来说问题发生了改变,不再是求中位数
其实求中位数本质上是求第len/2小的数,所以可以写求第k小的数
在排除一部分数后,求取的k也随之改变,注意递归的边界条件

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int left = (m+n+1)/2;
        int right = (m+n+2)/2;
    return (getKth(nums1,0,m-1,nums2,0,n-1,left)+getKth(nums1,0,m-1,nums2,0,n-1,right))*0.5;
    }

    int getKth(vector<int>& nums1,int start1,int end1,
    vector<int>& nums2,int start2,int end2,int k){
        int len1 = end1 - start1 + 1;
        int len2 = end2 - start2 + 1;
        //处理边界
        if (len2 == 0) return nums1[start1 + k - 1];//空集的情况
        if (len1 == 0) return nums2[start2 + k - 1];//空集的情况
        if (k == 1) return min(nums1[start1], nums2[start2]);//k规模缩减至1
        int i = start1 + min(len1, k / 2) - 1;//取中间值或边界
        int j = start2 + min(len2, k / 2) - 1;//取中间值或边界
         if (nums1[i] > nums2[j])//
            //缩小问题规模,数组二从j+1开始,其前面的数必然不是第k小,同时k发生改变
            return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
            //否则从数组一i+1开始,k发生改变
        else return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));

    }
};

标签:正序,int,start1,中位数,nums1,start2,vector,LeetCode,nums2
来源: https://www.cnblogs.com/929code/p/16387330.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有