zoukankan      html  css  js  c++  java
  • **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))
        }
    }
    
  • 相关阅读:
    SQLite 的连接串
    输入数组长度大于此表中的列数
    MVC3.0入门学习笔记页面传值ViewData
    MVC3.0入门学习笔记页面传值TempData
    在控制台程序中显示进度
    WCF学习笔记(1) 一个简单的wcf实例
    webBrowser 操作无ID元素
    webBrowser 设置文本框
    cookie总结
    checkbox是否被选择
  • 原文地址:https://www.cnblogs.com/ganshuoos/p/14011632.html
Copyright © 2011-2022 走看看