【LeetCode-hot100系列】4.中位数 |刷题打卡

188 阅读2分钟

题目描述

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

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

思路

这题主要考验我们怎么把俩个有序数组中的元素关联起来,知道他们在整体元素中的大小位置

1.暴力求解

将俩个数组合并为一个数组,利用sort()排序方法整理元素之间的大小,并且排序完成后的数组是知道他们元素位置和大小的

var findMedianSortedArrays = function(nums1, nums2) {
    let result = nums1.concat(nums2);
    result.sort((a,b)=>a-b);
    let length = result.length;
    if(length%2 === 0){
        return (result[length/2]+result[length/2-1])/2;
    }else{
        return result[Math.floor(length/2)];
    }
}; 
分析
  • 将俩个数组合并为一个数组result
  • 将result数组重新排序
  • 利用result数组的长度得出其中位数所在位置

由于sort排序使用的是插入排序和快速排序 时间复杂度为O((m+n)log(m+n))

2. 双指针排序

还是将两个数组合并为一个数组,但是利用双指针的方法缩减时间复杂度

var findMedianSortedArrays = function(nums1, nums2) {
    let reIndex = nums2.length-1;
    for(let i = nums1.length-1; i>=0; i--){
        while(nums2[reIndex]>=nums1[i] && reIndex > -1){
            nums1.splice(i+1,0,...(nums2.splice(reIndex,1)));
            reIndex--;
        }
    }
    const result = nums2.concat(nums1);
    const length = result.length;
   
    return length%2 ?  result[Math.floor(length/2)] : (result[length/2]+result[length/2-1])/2;
}; 
分析
    1. 外层循环控制nums1数组元素,内层循环控制nums2数组元素
    1. 将nums1数组与nums2数组的元素利用双指针法从末尾最大的数开始进行比较
    1. nums1[i]<nums2[reIndex]的话,将下标为reIndex的元素插入到nums1[i]的后面
    1. 当for循环结束时,只是将大于等于nums1[0]的nums2数组元素排好序 考虑特殊情况:
  • 当nums2数组其中部分元素可能小于nums1[0]

  • 当其中一个数组为空时

因此在第四步加上一个步骤,在将将下标为reIndex的元素插入到nums1[i]的后面的同时,将这个元素从nums2中删除

为什么删除呢? nums2数组其中部分元素可能小于nums1中最小的元素,为了方便循环结束后,将剩下的nums2数组元素和已经排好序的nums1数组元素合并

合并操作的另一个原因: 防止其中一个数组是空数组

nums2.concat(nums1)

3. 二分查找

将时间复杂度缩减到O(log(m+n))

分析

这个我实在是能力有限 只能给贴一个官方视频了

www.bilibili.com/video/BV1Xv…

总结

  • 遇到每一道算法题,首先去思考它究竟需要怎么样的答案,不要偏题很重要。
  • 理清楚思路后才开始敲代码,不要着急
  • 一般暴力破解之后,都可以再优化,好好想想还是可以的

本文正在参与「掘金 2021 春招闯关活动」, 点击查看【 活动详情】