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
相关推荐
掉鱼的猫39 分钟前
Solon AI + MCP实战:5行代码搞定天气查询,LLM从此告别数据孤岛
java·openai·mcp
带刺的坐椅1 小时前
Solon AI + MCP实战:5行代码搞定天气查询,LLM从此告别数据孤岛
java·mcp·solon-ai
androidwork2 小时前
嵌套滚动交互处理总结
android·java·kotlin
草履虫建模2 小时前
Tomcat 和 Spring MVC
java·spring boot·spring·spring cloud·tomcat·mvc·intellij-idea
蒟蒻小袁2 小时前
力扣面试150题--实现Trie(前缀树)
leetcode·面试·c#
电院工程师2 小时前
轻量级密码算法CHAM的python实现
python·嵌入式硬件·算法·安全·密码学
大白曾是少年2 小时前
哈希表三种数据结构在leetcode中的使用情况分析
数据结构·leetcode·散列表
枣伊吕波2 小时前
第十三节:第七部分:Stream流的中间方法、Stream流的终结方法
java·开发语言
天天摸鱼的java工程师2 小时前
Kafka是如何保证消息队列中的消息不丢失、不重复?
java·后端·kafka
天天摸鱼的java工程师2 小时前
SpringBoot 自动配置原理?@EnableAutoConfiguration 是如何工作的?
java·后端