leetcode hot100【LeetCode 4.寻找两个正序数组的中位数】java实现

LeetCode 4.寻找两个正序数组的中位数

题目描述

给定两个大小分别为 mn 的正序(从小到大)数组 nums1nums2

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

示例 1:

输入:
nums1 = [1, 3],nums2 = [2]
输出: 2.0

示例 2:

输入:
nums1 = [1, 2],nums2 = [3, 4]
输出: 2.5

Java 实现代码

java 复制代码
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return findMedianSortedArrays(nums2, nums1); // 确保nums1较短
        }
        
        int m = nums1.length;
        int n = nums2.length;
        int left = 0, right = m;
        int maxLeft = 0, minRight = 0;
        
        while (left <= right) {
            int i = left + (right - left) / 2;
            int j = (m + n + 1) / 2 - i;
            
            int nums1LeftMax = (i == 0) ? Integer.MIN_VALUE : nums1[i - 1];
            int nums1RightMin = (i == m) ? Integer.MAX_VALUE : nums1[i];
            int nums2LeftMax = (j == 0) ? Integer.MIN_VALUE : nums2[j - 1];
            int nums2RightMin = (j == n) ? Integer.MAX_VALUE : nums2[j];
            
            if (nums1LeftMax <= nums2RightMin && nums2LeftMax <= nums1RightMin) {
                maxLeft = Math.max(nums1LeftMax, nums2LeftMax);
                minRight = Math.min(nums1RightMin, nums2RightMin);
                break;
            } else if (nums1LeftMax > nums2RightMin) {
                right = i - 1;
            } else {
                left = i + 1;
            }
        }
        
        if ((m + n) % 2 == 1) {
            return maxLeft;
        } else {
            return (maxLeft + minRight) / 2.0;
        }
    }
}

解题思路

  1. 二分查找法

    为了满足时间复杂度要求 O(log (m+n)),可以使用二分查找法:

    • 我们将较短的数组设为 nums1,较长的数组设为 nums2。总是假设 m <= n
    • nums1 上进行二分查找,将数组分割成两个部分,使得左边部分的元素总数等于右边部分。
    • 使用二分查找不断调整分割点,直到找到正确的分割,使得左半部分的最大值 ≤ 右半部分的最小值。

    设分割点为 ij,满足以下条件:

    • nums1[i-1] <= nums2[j]
    • nums2[j-1] <= nums1[i]
  2. 中位数计算

    • 如果总长度是奇数,中位数为 max(nums1[i-1], nums2[j-1])
    • 如果总长度是偶数,中位数为 (max(nums1[i-1], nums2[j-1]) + min(nums1[i], nums2[j])) / 2

复杂度分析

  • 时间复杂度:O(log(min(m, n))),其中 m 和 n 分别是两个数组的长度。这是因为我们在较小的数组上进行二分查找。
  • 空间复杂度:O(1)。我们只使用了常量级别的额外空间。

执行过程示例

示例 1: nums1 = [1, 3], nums2 = [2]

  1. 初始化m = 2, n = 1left = 0, right = 2 交换数组使得 nums1 是较短数组。

  2. 第一次迭代

    • i = 1, j = 1
    • nums1[i-1] = 1, nums1[i] = 3
    • nums2[j-1] = 2 满足 nums1[i-1] <= nums2[j]nums2[j-1] <= nums1[i]
  3. 计算中位数

    • 奇数总数,max(1, 2) = 2,返回 2.0

示例 2: nums1 = [1, 2], nums2 = [3, 4]

  1. 初始化m = 2, n = 2left = 0, right = 2。无需交换数组。

  2. 第一次迭代

    • i = 1, j = 1
    • nums1[i-1] = 1, nums1[i] = 2
    • nums2[j-1] = 3, nums2[j] = 4 条件不满足,调整 left = i + 1 = 2
  3. 第二次迭代

    • i = 2, j = 0
    • nums1[i-1] = 2
    • nums2[j] = 3 满足条件。
  4. 计算中位数

    • 偶数总数,(max(2, 1) + min(3, 4)) / 2 = (2 + 3) / 2 = 2.5
相关推荐
刚学HTML20 分钟前
leetcode 05 回文字符串
算法·leetcode
Yan.love34 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
椰椰椰耶37 分钟前
【文档搜索引擎】搜索模块的完整实现
java·搜索引擎
大G哥37 分钟前
java提高正则处理效率
java·开发语言
AC使者39 分钟前
#B1630. 数字走向4
算法
冠位观测者44 分钟前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
智慧老师1 小时前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm1 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca2 小时前
洛谷 P1706 全排列问题 C语言
算法