Leetcode - 熟能生巧 之 1 - ?

Posted 一杯敬朝阳一杯敬月光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode - 熟能生巧 之 1 - ?相关的知识,希望对你有一定的参考价值。

目录

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


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,一个指向nums2,时间复杂度 O(n)。

二: 二分查找

可以将该题转换成查找两个各自有序数组的第 k 小数, help 函数就是具体执行寻找第 k 小数的函数。注意第 k 用下标表示是 k - 1。

  • 二分,每次只在两个数组中看 k // 2 - 1 的数
    • 若 nums1[k // 2 - 1] <= nums2[k // 2 - 1],则 nums1[new_idx1] 小的最多只有 nums1 的前 k // 2 - 1 个数和 nums2 的前 k // 2 - 1 个数,即比 nums1[new_idx1] 小的最多 k - 2 个数,即第 k 小的数 不存在于 nums1[new_idx1] 或 nums2[new_idx2] 之前,且 nums1[new_idx1] 最多是第 k - 1 小的数,所以我们可以排除掉 nums1[new_idx1] 及其之前的,还有 nums2[new_idx2] 之前的,但是 nums2[new_idx2] 待定,所以 new_idx1 右移 1, k 相应变化
    • 若 nums1[k // 2 - 1] > nums2[k // 2 - 1],思路同上。
  • 推出条件,当有一个数组已经遍历完毕,则第 k 小数只会出现在另一个数组,可以轻易求出,这边 -1,是因为第 k 小数折算成下标需要减一;另一种可退出情况是,两个数组都有值,但是 k = 1,这个时候也能轻易求出,两者谁最小取谁。
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        # 寻找第k大数
        def help1(idx1, idx2, k):
            if idx1 == m:
                return nums2[k + idx2 - 1]
            if idx2 == n:
                return nums1[k + idx1 - 1]
            if k == 1:
                return min(nums1[idx1], nums2[idx2])
            
            new_idx1 = min(m - 1, k // 2 - 1 + idx1)
            new_idx2 = min(n - 1, k // 2 - 1 + idx2)
            p1, p2 = nums1[new_idx1], nums2[new_idx2]
            if p1 <= p2:
                k -= new_idx1 - idx1 + 1
                return help1(new_idx1 + 1, idx2, k)
            else:
                k -= new_idx2 - idx2 + 1
                return help1(idx1, new_idx2 + 1, k)

        def help(k):
            idx1, idx2 = 0, 0
            while True:
                if idx1 == m:
                    return nums2[k + idx2 - 1]
                if idx2 == n:
                    return nums1[k + idx1 - 1]
                if k == 1:
                    return min(nums1[idx1], nums2[idx2])
                
                new_idx1 = min(m - 1, k // 2 - 1 + idx1)
                new_idx2 = min(n - 1, k // 2 - 1 + idx2)
                p1, p2 = nums1[new_idx1], nums2[new_idx2]
                if p1 <= p2:
                    k -= (new_idx1 - idx1 + 1)
                    idx1 = new_idx1 + 1
                else:
                    k -= (new_idx2 - idx2 + 1)
                    idx2 = new_idx2 + 1

        m, n = len(nums1), len(nums2)
        length = m + n
        one = help1(0, 0, (length + 1) // 2)
        # one = help((length + 1) // 2)
        if length % 2 == 1:
            return one
        else:
            # return (one + help(length // 2 + 1)) * 1. / 2
            return (one + help1(0, 0, length // 2 + 1)) * 1. / 2

以上是关于Leetcode - 熟能生巧 之 1 - ?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 之 验证表单

构建之法终于到手了

Effective Java 读书笔记之五 枚举和注解

手撕算法之冒泡选择插入希尔排序

Node.js 切近实战 之图书管理系统

初一数学教案有序数对