欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二分查找:力扣4. 寻找两个正序数组的中位数

程序员文章站 2022-06-17 19:50:18
...

1、题目描述:

二分查找:力扣4. 寻找两个正序数组的中位数

2、题解:

方法1:暴力法
思路:

1、使用归并的方式,合并两个有序数组,得到一个大的有序数组。大的有序数组的中间位置的元素,即为中位数。

2、不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是
已知的。维护两个指针,初始时分别指向两个数组的下标 0 的位置,每次将指向较小值的指针后移一位(如果一个指针已经
到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。

合并两个有序的数组后找中位数

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        #暴力法,合并两个有序的数组
        res = []
        m,n = len(nums1),len(nums2)
        if m == 0:
            if n % 2 == 0:
                return (nums2[n//2] + nums2[n // 2 - 1]) / 2
            else :
                return nums2[n // 2]
        if n == 0:
            if m % 2 == 0:
                return (nums1[m // 2] + nums1[m // 2 - 1]) / 2
            else:
                return nums1[m // 2]
        i ,j = 0,0
        while i < m and j < n:
            if nums1[i] < nums2[j]:
                res.append(nums1[i])
                i += 1
            else:
                res.append(nums2[j])
                j += 1
        res += nums1[i:] if i < m else nums2[j:]
        size = len(res)
        if size % 2 == 0:
            return (res[size // 2] + res[size // 2 - 1]) / 2
        else:
            return res[size // 2]

方法2:二分查找
思路:

中位数的定义:当m + n为奇数时,中位数是两个有序数组的第(m+n)/2个元素,当m+n为偶数时,中位数是(m+n)/2(m+n)/2+1
个元素的平均值。所以可以转化成寻找两个有序数组中的第k小的数,k为(m+n)/2(m+n)/2+1
- 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
- 这里的 "/" 表示整除
- nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1- nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1- 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2- 这样 pivot 本身最大也只能是第 k-1 小的元素
- 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
- 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
- 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数

Python代码如下:

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        #二分查找
        def getKthElement(k):
            index1,index2 = 0,0
            while True:
                #特殊情况
                if index1 == m:
                    return nums2[index2 + k -1]
                if index2 == n:
                    return nums1[index1 + k - 1]
                if k == 1:
                    return min(nums1[index1],nums2[index2])

                #一般情况
                newIndex1 = min(index1 + k // 2 - 1,m - 1)
                newIndex2 = min(index2 + k // 2 - 1 , n - 1)
                pivot1,pivot2 = nums1[newIndex1],nums2[newIndex2]
                if pivot1 <= pivot2:
                    k -= newIndex1 - index1 + 1
                    index1 = newIndex1 + 1
                else:
                    k -= newIndex2 - index2 + 1
                    index2 = newIndex2 + 1
        m,n = len(nums1),len(nums2)
        totalLen = m + n
        if totalLen % 2 == 1:
            return getKthElement((totalLen + 1) // 2)
        else:
            return ((getKthElement(totalLen // 2)) + getKthElement(totalLen // 2 + 1)) / 2

3、复杂度分析:

方法1:
时间复杂度:O(M+N),M、N分别为两个数组的长度
空间复杂度:O(M+N)
方法2:
时间复杂度:O(log(M+N)),M、N分别为两个数组的长度
空间复杂度:O(1)

相关标签: LeetCode