leetcode刷题笔记四 两个有序序列的中位数
原地址:两个有序序列的中位数
问题描述:
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)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
思路分析:
1.不考虑复杂度的情况下,最简单直接的方法是将两个数组进行合并,对合并后的数组进行排序,根据合并后数组的长度的奇偶获取对应的中位数位置。
代码如下:
def findMedianSortedArrays(nums1: Array[Int], nums2: Array[Int]): Double = { val nums = (nums1 ++ nums2).sorted if (nums.length%2 == 1){ return nums(nums.length/2) } else{ return (nums(nums.length/2-1)+nums(nums.length/2))/2.0 } }
执行结果:
2.对上一种思路的优化,问题的本质在于寻找有序序列中第K个数,可以使用计数器进行计数,依据遍历至第K次进行返回。
3.博客https://www.cnblogs.com/bonelee/p/10217507.html中提到了一种‘割’的方法。获取第K大数的过程,是对两个数组进行分割,分割为前K-1个数,第K大数, K之后的数。
以单数组为例,其过程就是对第K大数进行分割。
对于本题中的两数组的情况,假定
...LA Ca Ra... ...LB CB RB... 由于数组本身是有序的,LA <= RA , LB <= RB,CA CB为分割线
// func findMedianSortedArrays(nums1 []int, nums2 []int) float64 { //获取整个字符串长度 total := len(nums1) + len(nums2) //总长度为偶数,中位数考虑中间位置2个 if (total % 2 == 0) { left := find(nums1, 0, nums2, 0, total/2) right := find(nums1, 0, nums2, 0, total/2 + 1) //fmt.Printf("left: %d, right: %d, ans: %f", left, right, float64(left +right)/2) return float64(left + right)/2 } else { //否则只考虑最中间的一个 return float64(find(nums1, 0, nums2, 0, total/2 + 1)) } return 0.0 } func find(nums1 []int, i int, nums2 []int, j int, k int) int { //保证nums1 长度 小于等于 nums2长度 if len(nums1) - i > len(nums2) - j { return find(nums2, j, nums1, i, k) } //只取1个时 if k == 1{ //若nums1 已经遍历完了,返回nums2的遍历的头部 if len(nums1) == i{ return nums2[j] } else if nums1[i] < nums2[j] { //否则,取二者头部较小的元素 return nums1[i] } else { return nums2[j] } } //若nums1 已经遍历完了,返回nums2的遍历结果 if len(nums1) == i { return nums2[j + k - 1] } //由于nums1较短,需要判断nums1是否能到达i + k/2 si := 0 if len(nums1) < i + k/2 { si = len(nums1) } else { si = i + k/2 } sj := j + k - k/2 //根据指定位置的对比,判断哪一部份数被排除 if nums1[si-1] > nums2[sj-1] { return find(nums1, i, nums2, sj, k-(sj-j)) } else { return find(nums1, si, nums2, j, k-(si-i)) } }