leetcode 4.寻找两个有序数组的中位数(Golang)

94 阅读3分钟

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

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

算法的时间复杂度应该为 O(log (m+n)) 。

示例 1:

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

示例 2:

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

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -106 <= nums1[i], nums2[i] <= 106

解答:
解法1:
这道题最简单的方法就是对两个数组分别设置两个指针,对数组进行遍历,同时初始化m1和m2用于存储最大的数和第二大的数字,当遍历到i==mid时,就意味着我们已经获取了数组的中位数,然后判断一下,数组是奇数还是偶数,奇数则返回m1,偶数则返回(m1+m2)/2

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {  
l1, l2 := 0, 0  
len1, len2 := len(nums1), len(nums2)  
m1, m2 := float64(0.0), float64(0.0)  
mid := int((len1 + len2) / 2)  
for i := 0; i <= mid; i++ {  
if l2 >= len2 || (l1 < len1 && nums1[l1] <= nums2[l2]) {  
m2 = m1  
m1 = float64(nums1[l1])  
l1 += 1  
} else {  
m2 = m1  
m1 = float64(nums2[l2])  
l2 += 1  
}  
}  
if (len1+len2)%2 == 0 {  
return (m1 + m2) / 2  
} else {  
return m1  
}  
}

解法2:
为了进一步降低时间复杂度,对于偶数数组,要寻找第k(数组长度的一半)小的数和第k+1小的数,对于奇数数组,寻找第k+1小的数,设置一个mid指针,判断两个数组中k/2位置上的数字大小,将较小的数字全部排除(他们不可能是中位数),然后修改k=k-k/2(k减去被排除的数字个数),当k=1时,返回两个数组中的最小数字。
特殊情况:当mid大于数组长度导致溢出时,如果溢出的那个数组最后一位数比另一个数组的mid位数字小,排除所有溢出数组中的数字,否则正常进行下一次循环

func kmax(nums1 []int, nums2 []int, k int) int {
	for k > 1 {
		mid := int(k/2) - 1
		if mid+1 > len(nums1) {
			if len(nums1) > 0 && nums2[mid] > nums1[len(nums1)-1] {
				return nums2[k-len(nums1)-1]
			}
			nums2 = nums2[mid+1:]
			k = k - int(k/2)
			continue
		}
		if mid+1 > len(nums2) {
			if len(nums2) > 0 && nums1[mid] > nums2[len(nums2)-1] {
				return nums1[k-len(nums2)-1]
			}
			nums1 = nums1[mid+1:]
			k = k - int(k/2)
			continue
		}
		n1, n2 := nums1[mid], nums2[mid]
		if n1 <= n2 {
			nums1 = nums1[mid+1:]
		} else {
			nums2 = nums2[mid+1:]
		}
		k = k - int(k/2)
	}
	if len(nums2) == 0 {
		return nums1[0]
	} else if len(nums1) == 0 {
		return nums2[0]
	} else if nums1[0] <= nums2[0] {
		return nums1[0]
	} else {
		return nums2[0]
	}
}
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
	k := len(nums1) + len(nums2)
	if k%2 == 1 {
		k = int(k/2) + 1
		return float64(kmax(nums1, nums2, k))
	} else {
		k = int(k / 2)
		res := float64(kmax(nums1, nums2, k)+kmax(nums1, nums2, k+1)) / 2
		fmt.Println(kmax(nums1, nums2, k+1))
		return res
	}
}