**leetcode刷题笔记四 两个有序序列的中位数**

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
   }
 }

执行结果:

image-20200405042852060

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))
    }
}
posted @ 2020-11-20 16:33  ganshuoos  阅读(93)  评论(0编辑  收藏  举报