webjs求数组的中位数‘_求两个有序数组的中位数

947cee830a3a3c9fa99a8100e12addb1.png
package main
import (
	"fmt"
	"math"
)
/*
	给定两个大小为 m 和 n 的有序数组 A 和 B,请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
实例:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
-----------------
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
*/

/**
算法解析:
中位数:将一个集合划分为两个长度相等的子集,其中一个子集中的元素总是大于另一个子集中的元素。
1. 两个有序的数组分别为:A和B。其中A长度为m,B长度为n
我们把A分成两部分:
		left(A)    		 |   		right(A)
	A[0],A[1]...A[i-1]   |	A[i],A[i+2]...A[m-1]
其中len(left(A)) + len(right(A)) = m

把B分成两部分:
		left(B)    		 |   		right(B)
	B[0],B[1]...B[j-1]   |	B[j],B[j+2]...B[n-1]
其中len(left(B)) + len(right(B)) = n

2. 所以我们把两个数组结合到一起
		left_part	|	right_part
	left(A)+left(B) | right(A)+right(B)
其中:len(left_part) = i + j; len(right_part) = m-i+n-j
要找到AB两个数组的中位数,则需满足:
len(left_part) == len(right_part);如果m+n总长度为奇数则这里把多出的哪一个元素放在左边,所以len(left_part) == len(right_part)+1
max(left_part) <= min(right_part);由于数组A和数组B都是有序数组,则需满足A[i-1] <= B[j], B[j-1] <= A[i]
转换成公式如下:
i+j = m-i+n-j+1
i+j = (m+n+1)/2
j = (m+n+1)/2 - i; 此时当i=m临界值时,j = (n-m+1)/2, 所以n >= m

3. 先通过二分法方式定位数组A中的一个元素,再通过上面的公式也就能确定数组B中的元素了
设imin := 0; imax := m,在[imin,imax]中进行搜索
i = imin+imax / 2; 则 j = m+n+1+imin+imax / 2才能满足len(left_part) == len(right_part)
此时我们已经满足了len(left_part) == len(right_part)
下面需要满足A[i-1] <= B[j]&& B[j-1] <= A[i]
但是我们会遇到不满足的情况
比如:
如果A[i-1] > B[j],则i需要减少,i和j是成反相关的,所以j就会增加,通过二分法,则i会向左边分,i= i+imin / 2
如果B[j-1] > A[i],则j需要减少,i则需要增加,i会向右边分, i = i + imax / 2
代码实现如下:
*/

// findMedianSortedArrays查找两个数组的中位数
func findMedianSortedArrays(A []float64, B []float64) float64 {
	// 通过上面的分析得,len(B) >= len(A)
	if len(A) > len(B) {
		temp := A
		A = B
		B = temp
	}

	m := len(A)
	n := len(B)
	// 通过上面的分析,通过二分法先锚定A中的i
	imin := 0
	imax := m

	for imin <= imax {
		i := (imin + imax) / 2
		j := (m+n+1)/2 - i
		//
		if A[i-1] > B[j] && i > imin{
			// i需要减少,则下一个i在二分法的左边
			imax = i
		} else if B[j-1] > A[i] && i < imax{
			// i需要增加,则下一个i在二分法中的右边
			imin = i
		} else {
			// 表示满足条件A[i-1] <= B[j]&& B[j-1] <= A[i]

			// 计算中位数,找到左边的最大值和右边的最小值
			leftMax := 0.0
			if i == 0  {
				// 表示左边只有B
				leftMax = B[j-1]
			} else if j == 0 {
				// 表示左边只有A
				leftMax = A[i-1]
			} else {
				leftMax = math.Max(A[i-1],B[j-1])
			}
			if (m+n)%2 == 1 {
				return leftMax
			}

			// 找到右边的最小值
			rightMin := 0.0
			if i == m {
				// 表示右边只有B
				rightMin = B[j]
			} else if j == n {
				// 表示右边只有A
				rightMin = A[i]
			} else {
				rightMin = math.Min(A[i],B[j])
			}
			return (leftMax + rightMin) / 2
		}

	}
	// 表示没有找到
	return 0.0
}

func main() {
	A := []float64{1,3}
	B := []float64{2,3,4,5}
	middle := findMedianSortedArrays(A,B)
	fmt.Println(middle)
}

7d567389eff628d37907bdd979478267.png
【欢迎关注本人微信公众号】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值