美文网首页算法学习打卡计划
leetcode第四题 —— 计算两个数组中位数

leetcode第四题 —— 计算两个数组中位数

作者: 不分享的知识毫无意义 | 来源:发表于2019-11-07 23:25 被阅读0次

    1.题目

    原题:

    给定两个大小为m和n的有序数组nums1和nums2。请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。你可以假设nums1和nums2不会同时为空。

    例子:

    输入:nums1 = [1, 3],nums2 = [2]
    输出:2.0
    

    2.解析

    这道题的解法有很多种,尤其是对于python而言,很多内置函数的使用让求解变得很方便,此题的关键在于满足时间复杂度。为了锻炼算法思维,尽量不借助于python的内置函数实现,主要思路有两种。

    • 第一种,将两个数组合并,合并时要满足原来的大小关系,然后根据中位数的寻找方法得到最后的中位数。这种方法的算法复杂度是O(m+n)其实不能满足题目要求,但leetcode上测试是通过的,效率比较低,思路好想。
    • 第二种,二分法,题目说算法复杂度是o(log(m+n)),明显提示要用二分法,并且可以用递归的思路做这道题。

    3.python代码

    3.1 思路1代码

    其实就是一个数组的遍历组合,但是要保证数据的排序,所以进行了一个数据大小的比较,思路很清晰。

    class Solution:
        def getmid(self, num):
            m = len(num)
            if m % 2 == 0:
                return (num[m // 2 - 1] + num[m // 2]) / 2
            else:
                return num[m//2]
    
        def findMedianSortedArrays(self, nums1, nums2):
            if nums1 is None:
                return self.getmid(nums2)
            if nums2 is None:
                return self.getmid(nums1)
            i = 0
            j = 0
            num_extend = []
            while i < len(nums1) and j < len(nums2):
                if nums1[i] <= nums2[j]:
                    num_extend.append(nums1[i])
                    i += 1
                elif nums1[i] > nums2[j]:
                    num_extend.append(nums2[j])
                    j += 1
            if i < len(nums1):
                num_extend.extend(nums1[i:])
            if j < len(nums2):
                num_extend.extend(nums2[j:])
            midnum = self.getmid(num_extend)
            return midnum
    

    3.2 思路2代码

    思路2,笔者在写代码的时候趟了几个小坑,记录一下:

    • 递归函数需要有明确的函数出口,即使在递归调用的时候,返回值也要用return,否则会造成返回空值的情况。
    • log(m+n)复杂度,要求用二分法,二分法在排除前面几个数字后,找第k大的数会变成找第k-i-1大的数,但是如果是排除后面几个数字,找第k大的数仍然不变。
    class solution:
        def findMedianSortedArrays(self, nums1, nums2):
            m = len(nums1)
            n = len(nums2)
            k = (m + n) // 2
            if (m + n) % 2 == 0:
                num_mid = (self.findk(nums1, nums2, k) + self.findk(nums1, nums2, k-1))/2
            else:
                num_mid = self.findk(nums1, nums2, k)
            return num_mid
    
        def findk(self, nums1, nums2, k):
            if not nums1:
                return nums2[k]
            if not nums2:
                return nums1[k]
            i = len(nums1) // 2
            j = len(nums2) // 2
            m1 = nums1[i]
            m2 = nums2[j]
            if i + j < k:
                if m1 < m2:#一定不在nums1的前半部分
                    return self.findk(nums1[i+1:], nums2, k-i-1)
                else:
                    return self.findk(nums1, nums2[j+1:], k-j-1)
            else:
                if m1 < m2:
                    return self.findk(nums1, nums2[:j], k)
                else:
                    return self.findk(nums1[:i], nums2, k)
    

    相关文章

      网友评论

        本文标题:leetcode第四题 —— 计算两个数组中位数

        本文链接:https://www.haomeiwen.com/subject/lcepbctx.html