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题。虽然有一些题是抄题解的。

相关推荐
信奥卷王9 分钟前
[GESP202609 六级] 分树规划
算法
Su米苏11 分钟前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring
夏幻灵16 分钟前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
码云数智-园园23 分钟前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
老板一杯拿铁25 分钟前
Java 异常体系详解:从字节码原理到最佳实践
java
蜗牛互联网40 分钟前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端
禾小西1 小时前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨1 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言
小卡车5552 小时前
java反射、自定义注解的应用(自定义分页)
java