05.leetcode-04Median of Two Sorted Arrays(二分查找)

题目:

Median of Two Sorted Arrays寻找两个正序数组的中位数。

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]

nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2]

nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

解题分析:

很显然,这个题直接用暴力破解的话,时间复杂度为:O(m+n),空间复杂度为:O(m+n);

这个题的核心是:

一,要明白什么是中位数,以及它与偶数even个数和奇数odd个数的关系;

二是,由于是排好序的数组,很显然这个题采用的方法是:二分查找

二分查找的核心是:【1】partitioni + partitioni = (m + n + 1)/2;对数组 A 的做 partition 的位置是区间[0,m];

并且,【2】partition后,maxLeftA <= minRightB && maxLeftB <= minRightA,

满足这两个条件的话,中位数median就在这四个数(maxLeftA,minRightB,maxLeftB,minRightA)中,

如果m+n是奇数(总个数为奇数个):
median = max(maxLeftA, maxLeftB)
如果m+n是偶数(总个数为偶数个):
median = (max(maxLeftA, maxLeftB) + min(minRightA, minRightB)) / 2

这个题,虽然是个hard难度的题,但如果明白原理的话,还是很简单的;

本篇解题分析只列举了核心要点,具体讲解可以看一位印度朋友的讲解视频,个人感觉讲的非常好,通俗易懂,只要你肯静下心来花上不到半小时耐心听完!

YouTube原视频地址:https://www.youtube.com/watch?v=LPFhl65R7ww

国内B站搬运视频:https://www.bilibili.com/video/BV1Y4411G7YG?from=search&seid=10863350334241030260

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
          if(nums1.length > nums2.length){
            return findMedianSortedArrays(nums2, nums1);
        }

        int m = nums1.length;
        int n = nums2.length;

        int lo = 0;
        int hi = m;

        while(lo <= hi){

            // paartition i, j 要满足: i + j = (m + n + 1)/2
//            int i = lo + (hi - lo)/2;
//            int j = (m + n + 1)/2 - i;

            // 阿三哥关于partitioni和partitionj的写法:
            int i = (lo + hi)/2;
            int j = (m + n + 1)/2 - i;


            int maxLeftA = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];
            int minRightA = i == m ? Integer.MAX_VALUE : nums1[i];

            int maxLeftB = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];
            int minRightB = j == n ? Integer.MAX_VALUE : nums2[j];

            // 核心:
            if(maxLeftA <= minRightB && maxLeftB <= minRightA){
                // 如果总长度为偶数
                if((m + n)%2 == 0){
                    return (double)(Math.max(maxLeftA, maxLeftB) +  Math.min(minRightA, minRightB)) / 2;
                }else{
                    // 如果总长度为奇数
                    return (double) Math.max(maxLeftA, maxLeftB);
                }
            }else if(maxLeftA > minRightB){
                hi = i - 1;
            }else{
                // 也就是 maxLeftB > minRightA
                lo = i + 1;
            }
        }


        return 0.0;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值