【问题标题】:Median of two sorted arrays of different length两个不同长度的排序数组的中位数
【发布时间】:2018-06-28 02:51:18
【问题描述】:

我试图理解在 O(log(n+m)) 中解决此问题的算法,其中 n 和 m 是数组的长度。我冒昧地发布了该算法解释的链接:

https://www.geeksforgeeks.org/median-of-two-sorted-arrays-of-different-sizes/

我很难完全消化这个算法背后的想法。我可以看到这个想法是将其中一个数组的长度减少到 1 或 2,然后应用基本情况。基本情况是有道理的,但我想知道是否可以省略 n = 2 的基本情况而只处理 n = 1。我也不了解其余情况部分。对我来说,这看起来很奇怪,我们必须将数组 B[] 从开头切到 idx。这很奇怪,因为 idx 可以等于 B[] 的长度,所以我们会忽略整个数组。

【问题讨论】:

  • 你不明白二分搜索的工作原理吗?
  • -------------是的,二分搜索是通过将数据集减半来寻找事物的艺术。
  • 所以看我们有 array a = "aaaaaaaaaa" array b = "bbbbbbbbbbbbbbbbbbbb" 如果我​​们合并它们并排序它会像这样 "abababbabababbbbababaaba",我们的目标是在每一步中采取最数组的中间部分,所以 "ababab[bababbabbbbab]abaaba"
  • 我们想要 a1 和 a2、a1 和 b1、a1 和 b2、a2 和 b1、a2 和 b2,还是 b1 和 b2。所以我们有 6 种取一半元素的可能性,我们通过比较中间元素来决定,其中肯定是我们所有的中间元素
  • 但是其中一些案例没有意义,所以我们可以跳过它们

标签: algorithm


【解决方案1】:

TL;DR:

主要思想是,您可以从数字集中删除肯定小于(或等于)中位数的 N 个元素,只要删除肯定大于或等于的相同数量。

我们用一个例子来解释一下:

A=[1 2 3 9 10],B=[3 4 5 6 7 8 9]

中间标记的元素:

A=[1 2 3 9 10],B=[3 4 5 6 7 8 9]

总体中位数将介于 3 和 6 之间(含)。因此,如果我们删除两个小于 3 的元素和两个大于 6 的元素,我们仍然会有相同的中位数。我们从 A 中删除较小的元素,从 B 中删除较大的元素:

A=[3 9 10],B=[3 4 5 6 7]

现在我们删除一个大于 9 的元素(从 A 中)和一个小于 5 的元素(从 B 中):

A=[3 9],B=[4 5 6 7]

我们达到了案例 4(较小的数组有 2 个元素):算法要求中位数为

B[M/2], B[M/2 – 1], max(A[0], B[M/2 – 2]), min(A[1], B[M/2 + 1] ])

为 B[2], B[1], max(A[0], B[0]), min(A[1], B[3])

为 6, 5, max(3,4), min(9,7)

存在 [6 5 4 7]

该数组的中位数是 5.5。这就是正确的结果。

【讨论】:

  • 我们可以一直减少数据集直到其中一个数组的大小为 1 吗? A = [3],B = [5 6 7]
  • @Dan 你是对的,没有必要用二元素数组停止算法。 B中位数为5.5,A中位数为6,完全可以删除A中的9和B中的4。最后你可以删除A中的3和B中的7,使A为空,取中位数从 B 是 [5 6]。
  • @RalfKleberhoff 如果我们像你说的那样继续清空 A 并将 B 减少到 2,那么时间复杂度将为 O(log(max(m,n))) 而不是 O(log(min (m,n))) ??
【解决方案2】:
def findmedian(A,B):
    if len(A) > len(B):
        return findmedian(B,A)# always ensuring that we do the binsearch on the shorter arr
    x = len(A)
    y = len(B)
    start = 0# start and end of shorter arr
    end = x
    while (start <= end):
        partition_x = (start + end)//2# the mid of smaller arr, partition_x is an index
        partition_y = (x+y+1)//2 - partition_x# the suitable partition of larger arr to divide the arrs into equal halves
        if partition_x == 0:# if there is nothing on the left
            left_x = None
        if partition_x == x:# if there is nothing on the right
            right_x = sys.maxint# +inf
        if partition_y == 0:
            left_y = None# this is -inf similar to the case for smaller arr
        if partition_y == y:
            right_y = sys.maxint

        if (left_x <= right_y) and (left_y <= right_x):# all the elems on left are smaller than all the elems on right is ensured by
         #checking on the extremes only since arrs sorted. Also, the partition always makes equal halves, so found the right spot.
            if (x+y) % 2 == 0:
                return (max(left_x,left_y) + min(right_x,right_y))/2.0
            else:
                return max(left_x,left_y)# if the num of elems is odd
            elif left_x > right_y:# if we have come more towards right of smaller arr, then move left on smaller arr
                end = partition_x -1
            else:# if we have come more to the left
                start = partition_x + 1

【讨论】:

    【解决方案3】:
        class Solution(object):
          def findMedianSortedArrays(self, nums1, nums2):
          merged_array = (nums1 + nums2)
          merged_array.sort()
          l_m_a = len(merged_array)
          count = int(l_m_a / 2)
    
          if l_m_a % 2 == 1:
            median = merged_array[count]
            return median
          else:
            median_in_even = (merged_array[count] + merged_array[count - 1]) / 2
            return median_in_even
    

    【讨论】:

      【解决方案4】:

      对我来说,这只是几行 python 代码的几分钟,它通过了 leetcode 检查,运行时击败了 62% 的 Python3 在线提交。我的代码在这里:

      
      class Solution:
          def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
              n = len(nums1) + len(nums2)
              nums1.extend(nums2)  # merge two lists
              nums1.sort()  # sort it
              if n % 2 == 0:
                  return (nums1[n//2-1] + nums1[n//2])/2 # return the median for even n
              else:
                  return nums1[n//2] # return the median for odd n
      
      

      【讨论】:

      • 哦,现在我知道我错了。我的解决方案给出了 O(n log(n)) 的时间复杂度,但问题要求 O(log (n)) 的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 1970-01-01
      相关资源
      最近更新 更多