Leetcode 4. Median of Two Sorted Arrays (两个排序数组的中值)

##原题:

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))…

题目大意:给出两个有序的数字列表,长度分别为m,n。找到这两个列表中的中间值。(第一次出现了时间复杂度的要求噢)

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

Reference solution

仔细分析题目,nums1和nums2都已经是排好序了的,这就大大的降低了难度,让找到两个列表的中间值,其实我们可以拓展为找到两个列表的第k个值。当然这个是拓展部分了,对于这个题目,有不同的思路,最简单粗暴的就是将两个列表合并,之后进行排序,拍好序后进行寻找中间值就简单了。但是用传统的先合并再排序,效率想必会很低~

我们发现对于两个已经有序的列表(从小到大),其实有一个更优的排序方式:从小到大,依次进行列表元素的比较(为方便表述,小詹称两个列表为A,B),较小值放到一个新列表中,比如A中该位置的值较小,将其放到新的列表C中,同时将A列表下一个值继续与B中当前位置元素进行比较,以此类推。

这样的比较次数就比先合并在排序小很多啦!代码如下:


def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        #创建新列表,并将所有元素初始为0
        nums3 = [0] * (len(nums1)+len(nums2))
        #指定三个列表的索引,初始值为0
        l_i,r_i,i = 0,0,0
        #当输入两个列表都还存在元素没进行比较的时候,循环进行对比
        #并将较小值放入新列表,同时较小元素的列表和新列表索引加一
        while(l_i < len(nums1)) and (r_i < len(nums2)):
            if nums1[l_i] < nums2[r_i]:
                nums3[i] = nums1[l_i]
                l_i += 1
            else:
                nums3[i] = nums2[r_i]
                r_i += 1
            i += 1
        #当存在某一个列表所有元素已经比较完,即拍好了序
        #剩下那个列表剩下的值直接放入新列表对应位置即可
        if l_i != len(nums1):
            nums3[i:] = nums1[l_i:]
        else:
            nums3[i:] = nums2[r_i:]
        #注意‘/’和‘//’的区别
        #前者结果为float类型,后者为整除,结果为int型
        len_3 = len(nums3)
        #‘%’为取模运算,即看长度是否被2整除,即看偶数还是奇数
        if len_3 %2 != 0:
            return float(nums3[(len_3-1)//2])
        return (nums3[len_3//2 - 1]+nums3[len_3//2])/2
 

My solution

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        # total = [0] * (len(nums1) + len(nums2))
        total = []
        # count = len(total)
        
#       冒泡排序法
#         for i in range(0, count):
#             for j in range(i + 1, count):
#                 if total[i] > total[j]:
#                     total[i], total[j] = total[j], total[i]

        # # 选择排序
        # for i in range(0, count):
        #     min_index = i
        #     for j in range(i, count):
        #         if total[j] < total[min_index]:
        #             min_index = j
        #     total[min_index], total[i] = total[i], total[min_index]
            
        # # 插入排序
        # for i in range(1, count):
        #     key = i - 1
        #     mark = total[i]
        #     while key >= 0 and total[key] > mark:
        #         total[key + 1] = total[key]
        #         key -= 1
        #     total[key+1] = mark
        
#         # shell排序
        # gap = round(count / 2)    # 双杠用于整除(向下取整),在python直接用 “/” 得到的永远是浮点数
        # while gap >= 1:
        #     for i in range(gap, count):
        #         temp = total[i]
        #         j = i
        #         temp_two = total[j - gap]
        #         while j - gap >= 0 and total[j-gap] > temp:
        #             total[j] = total[j-gap]
        #             j -= gap
        #         total[j] = temp
        #     gap = round(gap / 2)
        
#         # 归并排序
        
#         total = self.merge_sort(total)
     
        # # 快速排序
        # total = self.quick_sort(total, 0, count-1)
        
        
        len_num1 = len(nums1)
        len_num2 = len(nums2)
        i = j = 0
        
        while i <= len_num1 -1 and j <= len_num2 - 1:
            if nums1[i] <= nums2[j]:
                total.append(nums1[i])
                i += 1
            else:
                total.append(nums2[j])
                j += 1
                
        if i == len_num1:
            total += nums2[j:]
        else:
            total += nums1[i:]
        count = len(total)
            
        
        if (count % 2) == 0:
            median = (total[int(count/2)] + total[int(count/2)-1]) / 2
        else:
            median = total[int(count/2)]
        return median
    
    # 归并排序
    def merge_sort(self, ary):
        
        if len(ary) <= 1:
            return ary
        
        median = int(len(ary)/2)
        left = self.merge_sort(ary[:median])
        right = self.merge_sort(ary[median:])
        return self.merge(left, right)
    
    def merge(self, left, right):
        res = []
        i = j = k = 0
        while(i < len(left) and j < len(right)):
            if left[i] < right[j]:
                res.append(left[i])
                i += 1
            else:
                res.append(right[j])
                j += 1
                
        res = res + left[i:] + right[j:]
        return res


    def quick_sort(self, total, start, end):
        
        # 快速排序
        if start < end:
            left = start
            right = end
            key = total[start]
            while (left < right):
                while (left < right) and total[right] >= key:
                    right -= 1
                if left < right:    # 说明上述while循环打破原因是total[right] <= key
                    total[left] = total[right]
                    left += 1
                while left < right and total[left] < key:
                    left += 1
                if left < right:
                    total[right] = total[left]
                    right -= 1
            total[left] = key

            self.quick_sort(total, start, left - 1)
            self.quick_sort(total, left + 1, end)
        return total

上述代码中注销掉的代码是在这个过程实验过的排序算法,可以用,只是为了重新复习排序,又将各大排序算法重新实现了一边,;事实上,只有bubble sort与select sort没能通过时间复杂度,其他算法均能通过只是性能一般。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值