二分查找

寻找两个正序数组的中位数

困难#4Java时间 O(log min(m,n))空间 O(1)

题目要做什么

两个非递减数组,至少一个非空。求合并后的中位数,要求 O(log(m+n)) 时间,不能直接合并排序。

题目示例输入nums1 = [1,3], nums2 = [2]
题目示例输出2

01 为什么这样做

在较短数组上二分切分位置 i,另一个数组的切分位置 j 由左侧总人数决定。左右两侧元素数量平衡,且两边所有左侧值不大于右侧值时,就能从分界值得到中位数。

始终成立的条件

两个切分位置满足 i+j=(m+n+1)/2;目标是让 leftA≤rightB 且 leftB≤rightA。

02 看见算法执行

动画与代码同步

修改输入,播放自己的例子

当前使用题目示例
修改输入会改变执行过程;预期输出用于核对结果。
数组 / nums步骤 1
执行状态
本次演示输出播放到最后查看

Solution.java参考解法
1class Solution {2    public double findMedianSortedArrays(int[] nums1, int[] nums2) {3        if (nums1.length > nums2.length) return findMedianSortedArrays(nums2, nums1);4        int m = nums1.length, n = nums2.length;5        int left = 0, right = m;6        while (left <= right) {7            int i = left + (right - left) / 2;8            int j = (m + n + 1) / 2 - i;9            int leftA = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];10            int rightA = i == m ? Integer.MAX_VALUE : nums1[i];11            int leftB = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];12            int rightB = j == n ? Integer.MAX_VALUE : nums2[j];13            if (leftA <= rightB && leftB <= rightA) {14                if ((m + n) % 2 == 1) return Math.max(leftA, leftB);15                return ((double) Math.max(leftA, leftB) + Math.min(rightA, rightB)) / 2;16            }17            if (leftA > rightB) right = i - 1;18            else left = i + 1;19        }20        throw new IllegalArgumentException("输入数组必须有序");21    }22}

键盘控制:A 后退 · D 前进

编程练习

↑↓ 选择↵ 打开Pagefind 全文检索