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

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

🔗 题目链接

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

📖 题目概要

给定两个大小分别为 mn正序(从小到大)数组 nums1nums2
请你找出并返回这两个正序数组的
中位数

要求 :算法的时间复杂度应该为 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题。虽然有一些题是抄题解的。

相关推荐
Flittly4 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了4 小时前
Java 生成二维码解决方案
java·后端
BothSavage8 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn8 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
人活一口气8 小时前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
烬羽10 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
NE_STOP10 小时前
Vibe Coding -- 完整项目案例实操
java
荣码10 小时前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing10 小时前
Google第三方授权登录
java·后端·程序员
明月光81810 小时前
从一行 @Builder 说起:重新拾起 Java 的 Lombok、注解与 Builder 模式
java