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
相关推荐
CodeCraft Studio11 分钟前
PPT处理控件Aspose.Slides教程:使用Java将PowerPoint笔记导出为PDF
java·笔记·pdf·powerpoint·aspose·ppt转pdf·java将ppt导出pdf
手握风云-13 分钟前
Java 数据结构第二十八期:反射、枚举以及 lambda 表达式
java·开发语言
熬了夜的程序员16 分钟前
【LeetCode】99. 恢复二叉搜索树
算法·leetcode·职场和发展
ᐇ95917 分钟前
Java Vector集合全面解析:线程安全的动态数组
java·开发语言
Kent_J_Truman21 分钟前
LeetCode Hot100 自用
算法·leetcode·职场和发展
还是码字踏实21 分钟前
算法题种类与解题思路全面指南:基于LeetCode Hot 100与牛客Top 101
算法·leetcode
毕设源码-朱学姐27 分钟前
【开题答辩全过程】以 广州网红点打卡介绍网站为例,包含答辩的问题和答案
java·eclipse
程序定小飞1 小时前
基于springboot的web的音乐网站开发与设计
java·前端·数据库·vue.js·spring boot·后端·spring
百锦再1 小时前
第1章 Rust语言概述
java·开发语言·人工智能·python·rust·go·1024程序员节
武昌库里写JAVA1 小时前
element-ui 2.x 及 vxe-table 2.x 使用 css 定制主题
java·vue.js·spring boot·sql·学习