Leetcode - Median of Two Sorted Arrays

本文介绍了一种高效算法,用于查找两个已排序数组的中位数,通过递归方式找到第k小的元素,实现了O(log(min(m,n)))的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

[分析] 暴力法是简单的,合并后返回中位数。优化的方法是参考[url]http://blog.youkuaiyun.com/yutianzuijin/article/details/11499917[/url]介绍的解法,awesome! 思路的关键点是将原问题转为寻找两排序数组中第 k 小的数,中位数即为第 (n + m) / 2 小的数, n和m分别为输入中A 和 B 两个数组的长度。
findKth 思路:假设A 和 B长度均不小于 k/2, 比较A[k/2 - 1] 和 B[k/2 - 1]:
(1) A[k/2 - 1] < B[k/2 - 1]
则A的前 k/2个元素是AB合并后的前 k - 1 小的元素中,也即 A[k/2 - 1]不可能是要找的第k个数。反证法证明推断:假设A[k/2 - 1] 在AB合并后出现在第k个元素或以后位置,不妨设就是第k个元素,则 B[k/2 - 1]至少为第 k+1个元素。因为 小于 A[k/2 - 1]至多有 (k/2 - 1) * 2 = k -2 个元素,这与A[k/2 - 1]是合并后第 k个数矛盾,得证。
(2) A[k/2 - 1] > B[k/2 - 1]
分析同(1)。
(3) A[k/2 - 1] = B[k/2 - 1]
则A[k/2 - 1] 就是合并后第 k 个数。
findKth 每次缩小一半规模,时间复杂度是 logk, 因此找寻中位数时间复杂度为 log((m + n) / 2)。


public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length + nums2.length;
if ((total & 1) == 0)
return (findKth(nums1, nums2, 0, 0, total / 2) + findKth(nums1, nums2, 0, 0, total / 2 + 1)) * 1.0 / 2;
else
return findKth(nums1, nums2, 0, 0, total / 2 + 1);
}
public int findKth(int[] nums1, int[] nums2, int off1, int off2, int k) {
if (nums1 == null || nums1.length == off1) return nums2[off2 + k - 1];
if (nums2 == null || nums2.length == off2) return nums1[off1 + k - 1];
if (k == 1) return Math.min(nums1[off1], nums2[off2]);
int m = nums1.length - off1;
int n = nums2.length - off2;
if (m > n) return findKth(nums2, nums1, off2, off1, k);
int part1 = Math.min(k / 2, m);
int part2 = k - part1;
if (nums1[off1 + part1 - 1] < nums2[off2 + part2 - 1])
return findKth(nums1, nums2, off1 + part1, off2, k - part1);
else if (nums1[off1 + part1 - 1] > nums2[off2 + part2 - 1])
return findKth(nums1, nums2, off1, off2 + part2, k - part2);
else
return nums1[off1 + part1 - 1];
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值