Leetcode热题 4. 寻找两个正序数组的中位数

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

知识点:二分、归并排序
时间:2021年4月13日
题目链接

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

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

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

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

示例 4
输入:nums1 = [], nums2 = [1]
输出:1.00000

示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -106 <= nums1[i], nums2[i] <= 106

解题思路

  1. 要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较 这里的 “/” 表示整除
  2. nums1 中小于等于 pivot1 的元素有 nums1[0 … k/2-2] 共计 k/2-1
  3. nums2 中小于等于 pivot2 的元素有 nums2[0 … k/2-2] 共计 k/2-1
  4. pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
  5. 这样 pivot 本身最大也只能是第 k-1 小的元素
  6. 如果 pivot = pivot1,那么 nums1[0 … k/2-1] 都不可能是第 k 小的元素。把这些元素全部 “删除”,剩下的作为新的 nums1 数组
  7. 如果 pivot = pivot2,那么 nums2[0 … k/2-1] 都不可能是第 k 小的元素。把这些元素全部 “删除”,剩下的作为新的 nums2 数组
  8. 由于我们 “删除” 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
  9. 注意边界的情况

代码

#include "cheader.h"
class Solution {
public:
    int getKth(vector<int>& nums1,vector<int> &nums2, int k){
        int index1 = 0,index2 =0;
        int m = nums1.size(), n = nums2.size();
        while(1){
            if(index1 == m) //当一个数组中到头了 就返回另一个的
                return nums2[index2+k-1];
            else if(index2 == n)
                return nums1[index1+k-1];
            else if(k == 1) //只需要一个数时 比较即可
                return min(nums1[index1],nums2[index2]);
            int tmp = k/2-1; // 注意tmp >= m 或者 tmp >= n的情况
            int newindex1 = min(index1 + tmp ,m-1);
            int newindex2 = min(index2 + tmp ,n-1);
            if(nums1[newindex1] <= nums2[newindex2]){
                k -= newindex1-index1+1; //排除一定不是的解
                index1 = newindex1+1;	//更新下标
            }else{
                k -= newindex2-index2+1;
                index2 = newindex2+1;
            }
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int a = nums1.size() + nums2.size();
        if(a % 2 == 1)
            return getKth(nums1,nums2,(a+1)/2);
        else
            return (getKth(nums1,nums2,a/2) + getKth(nums1,nums2,a/2+1))/2.0;
    }
    
    double findMedianSortedArrays2(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int x = 0,flag = 0;
        if((m+n)%2 == 1){
            flag = 0;
            x = (m+n+1)/2;
        }else{
            flag = 1;
            x = (m+n)/2+1;
        }
        vector<int> ans;
        int tmp = 0,index1 = 0,index2 = 0;
        while(tmp < x && index1 < m && index2 < n){
            if(nums1[index1] >= nums2[index2]){
                ans.push_back(nums2[index2]);
                index2++;
                tmp ++;
            }
            else{
                ans.push_back(nums1[index1]);
                index1++;
                tmp++;
            }
        }
        while(index1 == m && index2 < n && tmp < x){
            ans.push_back(nums2[index2]);
            index2++;
            tmp ++;
        }
        while(index2 == n && index1 < m && tmp < x){
            ans.push_back(nums1[index1]);
            index1++;
            tmp ++;
        }
        if(flag)
            return 1.0*(ans[x-1]+ans[x-2])/2;
        else
            return 1.0*ans[x-1];
        
    }
};
int main()
{
    vector<int> nums1{2};
    vector<int> nums2{};
    Solution s;
    cout << s.findMedianSortedArrays(nums1, nums2)<<endl;
    return 0;
}

今天也是爱zz的一天哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值