LeetCode 4:寻找两个正序数组的中位数 —— 二分查找法

LeetCode 4:寻找两个正序数组的中位数 ------ 二分查找法 题解

🔗 题目链接

👉 https://leetcode.cn/problems/median-of-two-sorted-arrays/

📖 题目概要

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

要求 :算法的时间复杂度应该为 O(log(m + n))。

示例 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

✅ 本题解法:二分切割法(最优解,AC代码)

核心思想

  1. 不合并数组 ,直接在两个数组上做二分查找
  2. 将两个数组左右切割,让左半部分整体 ≤ 右半部分
  3. 通过切割位置直接算出中位数
  4. 始终把短数组作为 nums1,减少二分次数

💡 详细解题思路

1. 核心原理:数组切割

把两个数组各分成左右两部分:

  • nums1 左:[0, i-1],右:[i, m-1]
  • nums2 左:[0, j-1],右:[j, n-1]

满足两个条件:

  1. 左半总长度 = 右半总长度(或多1)
    i + j = m - i + n - j + 1
    → 推导得:j = (m + n + 1) / 2 - i
  2. 左边所有数 ≤ 右边所有数
    nums1[i-1] ≤ nums2[j] 且 nums2[j-1] ≤ nums1[i]

2. 边界处理

  • 左边没数:用 Integer.MIN_VALUE
  • 右边没数:用 Integer.MAX_VALUE

3. 中位数计算

  • 总长度奇数:左边最大值就是中位数
  • 总长度偶数:(左边最大值 + 右边最小值) / 2.0

4. 二分调整切割点

  • nums1[i-1] > nums2[j]:i 太大 → 左移 r = i - 1
  • nums2[j-1] > nums1[i]:i 太小 → 右移 l = i + 1

✅ AC 代码

java 复制代码
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if(nums1.length > nums2.length) {
            int[] tmp = nums1;
            nums1 = nums2;
            nums2 = tmp;
        }
        int m = nums1.length; //元素少的数组
        int n = nums2.length;

        int l = 0, r = m;
        while(l <= r) {
            int i = (l + r) / 2;
            int j = (m+n+1) / 2 - i; //绳子总长减去i的长度
            int l1 = (i==0) ? Integer.MIN_VALUE : nums1[i-1];
            int r1 = (i==m) ? Integer.MAX_VALUE : nums1[i];
            int l2 = (j==0) ? Integer.MIN_VALUE : nums2[j-1];
            int r2 = (j==n) ? Integer.MAX_VALUE : nums2[j];
            // 满足条件
            if (l1<=r2 && l2<=r1) {
                if((m+n) % 2 == 1) {
                    return Math.max(l1,l2);
                } else {
                    return (Math.max(l1,l2) + Math.min(r1,r2)) / 2.0;
                }
            } else if(l1 > r2) {
                r = i - 1;
            } else {
                l = i + 1;
            }
        }
        return 0;
    }
}

⏱️ 复杂度分析

指标 复杂度 说明
时间复杂度 O(log(min(m,n))) 只对短数组二分
空间复杂度 O(1) 只用常数变量

📌 核心一句话总结

在两个有序数组上做二分切割,让左边整体 ≤ 右边,满足长度平衡后,直接从边界值计算中位数。


📝 高频面试问答

1. 为什么要把短数组放前面?

让二分次数变少,保证时间复杂度 O(log(min(m,n)))。

2. 为什么 j 这么算?

j = (m + n + 1) / 2 - i

保证左右两边长度相等或左边多1,方便取中位数。

3. 为什么要用 MIN/MAX 处理边界?

防止数组越界,同时不影响大小比较。

最后记录一下,第一遍刷完Leetcode的Hot100题。虽然有一些题是抄题解的。

相关推荐
Fuyo_111912 分钟前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
Sarvartha30 分钟前
Date、LocalDate、LocalTime、LocalDateTime、DateTimeFormatter类
java
jktantan32 分钟前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
阿俊-全栈开发1 小时前
LikeShop 多商户 Java 版商城微服务模块拆分与部署架构演进实践
java·微服务·架构·likeshop开源商城·多商户源码
揽星河..1 小时前
【C语言】猜数字游戏
c语言·算法·游戏
Wang's Blog1 小时前
Java 项目实战:交友项目 - 联系人列表
java·开发语言·交友
我命由我123451 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
frjc1 小时前
分布式服务拆分实战指南:从底层逻辑到面试话术
微服务·面试·职场和发展
LabVIEW开发1 小时前
CTM-3 红外测温仪 + LabVIEW 温度怎么测?
算法·labview·测试·labview程序
纪念 2292 小时前
C++算法(六)
开发语言·c++·算法