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
相关推荐
喵手1 小时前
玩转Java网络编程:基于Socket的服务器和客户端开发!
java·服务器·网络
再见晴天*_*2 小时前
SpringBoot 中单独一个类中运行main方法报错:找不到或无法加载主类
java·开发语言·intellij idea
hdsoft_huge5 小时前
Java & Spring Boot常见异常全解析:原因、危害、处理与防范
java·开发语言·spring boot
风中的微尘5 小时前
39.网络流入门
开发语言·网络·c++·算法
雨白6 小时前
Java 多线程指南:从基础用法到线程安全
android·java
Hungry_Shark6 小时前
IDEA版本控制管理之使用Gitee
java·gitee·intellij-idea
赛姐在努力.6 小时前
《IDEA 突然“三无”?三秒找回消失的绿色启动键、主菜单和项目树!》
java·intellij-idea
猎板PCB黄浩6 小时前
从废料到碳减排:猎板 PCB 埋容埋阻的绿色制造革命,如何实现环保与性能双赢
java·服务器·制造
ZzzK,6 小时前
JAVA虚拟机(JVM)
java·linux·jvm
西红柿维生素6 小时前
JVM相关总结
java·jvm·算法