【算法】求两个有序正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2
解释:合并数组 = [1,2,3] ,中位数 2

示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.5
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

方法一:

var findMedian1 = function(nums1, nums2) {
	const nums = nums1.concat(nums2);
	nums.sort((a, b) => {
		return a - b;
	}); 
	let median = nums.length % 2;
	return median ? nums[(nums.length - 1) / 2] : (nums[nums.length / 2] + nums[nums.length/2 - 1]) / 2;
}

时间复杂度:O(m+n)

方法二:划分数组
一个长度为 m 的数组,有 0 到 m 总共 m + 1 个位置可以切。

在这里插入图片描述

我们把数组 A 和数组 B 分别在 i 和 j 进行切割。

image.png
将i的左边和j的左边组成左半部分,i的右边和j的右边组成右半部分。

当两个数组的长度为偶数时,

  1. 左半部分的长度和右半部分的长度相等
i + j = m - i + n - j, 即i+j = (m+n) /2
因为m+n为偶数,因此i+j = (m+n+1)/2
  1. 左半部分的最大值小于等于右半部分的最小值

那么中位数为:(max(A[i-1], B[j-1]) + min(A[i], B[j])) / 2

当两个数组的长度为奇数时,

  1. 左半部分的长度比右半部分的长度大1
i + j = m - i + n - j +1,即 i+j = (m+n+1)/2
  1. 左半部分的最大值小于等于右半部分的最小值

那么中位数为:max(A[i-1], B[j-1])

j=(m+n+1)/2-i,由于 0 <= i <= m ,为了保证 0 <= j <= n,我们必须保证 m <= n。

下面讨论边界情况:
1.当 i = 0, 或者 j = 0,也就是切在了最前边。
在这里插入图片描述
当i为0时,左半部分最大值为B[j-1],当j为0时,左半部分最大值为A[i-1]

2.当 i = m 或者 j = n,也就是切在了最后边。
在这里插入图片描述
当i为m时,右半部分最小值为B[j],当j为n时,右半部分最大值为A[i]

所有的思路都理清了,最后一个问题,增加 i 的方式。当然用二分了。初始化 i 为中间的值,然后减半找中间的,减半找中间的,减半找中间的直到答案。

var findMedian2 = function(nums1, nums2) {
	if (nums1.length > nums2.length) {
		[nums1, nums2] = [nums2, nums1];
	}
	const m= nums1.length;
	const n= nums2.length;
	let min = 0;
	let max = m;
	let half = Math.floor((m + n +1) / 2);
	while (min <= max) {
		// 数组1的分界
		const i = Math.floor((min + max) / 2);
		// 数组2的分界
		const j = half - i;
		// 如果数组1的最大值大于数组2的最小值
		if (i > min && nums1[i - 1] > nums2[j]) {
			max = i - 1;
		} else if (i<max && nums1[i] < nums2[j-1]) {
			min = i + 1;
		} else {
			let left, right;
			if (i === 0) left = nums2[j-1];
			else if (j === 0) left = nums2[i-1];
			else left = Math.max(nums1[i - 1], nums2[j - 1]);
			if (i === m) right = nums2[j];
			else if (j === n) right = nums1[j];
			else right = Math.min(nums1[i], nums2[j]);
			return (m + n) % 2 ? left : (left + right) / 2;
		}
	}
	return 0;
};

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值