[LeetCode][golang] 4. 寻找两个正序数组的中位数

335 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述:

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.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-10 的 6次方 <= nums1[i], nums2[i] <= 10 的 6次方

思路分析:

  1. 计算两个数组的长度和 和 循环截止的下标。
    长度和的结果是奇数,则中位数是中间的单个值,循环截止的下标为中间的单个下标;结果是偶数,则中位数是位于中间的两个元素的平均值,循环截止的下标为中间两个下标中较大的下标。

  2. 定义当前值、上一个值和两个数组循环用的下标的三个变量。

  3. 循环处理,下标从 0 到循环截止的下标。

    1. 当前值赋值给上一个值。

    2. 如果数组 1 里和数组 2 里对应的下标位置都有值,则比较大小后,小的值设置给当前值,同时循环用的下标加 1 。

    3. 如果只有一个数组里在对应的下标位置有值,则设置给当前值,同时循环用的下标加 1 。

4。 1 中计算长度和的结果是奇数时,返回当前值;为偶数时,则返回当前值和上一个值的平均值。

AC 代码:

golang :

// 寻找两个正序数组的中位数
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
   // 数组元素个数
   ln1 := len(nums1)
   ln2 := len(nums2)
   ln := ln1 + ln2

   // 中间下标
   mid := 0
   isEven := false // 数组元素总个数是否为偶数标志
   if ln%2 == 1 {
      mid = (ln - 1) / 2
   } else {
      mid = ln / 2
      isEven = true
   }

   m := 0
   n := 0
   current := 0
   prev := 0
   
   for i := 0; i <= mid; i++ {
      // 上一个值
      prev = current

      if m < ln1 && n < ln2 {
         // 比较后小的值设置给当前值
         if nums1[m] < nums2[n] {
            current = nums1[m]
            m = m + 1
         } else {
            current = nums2[n]
            n = n + 1
         }
      } else if m < ln1 {
         // 当前值
         current = nums1[m]
         m = m + 1
      } else if n < ln2 {
         // 当前值
         current = nums2[n]
         n = n + 1
      }
   }

   if isEven {
      // 元素总个数为偶数时,取当前值和上一个值的和的平均值
      return float64(current+prev) / 2
   } else {
      // 元素总个数为奇数时,取当前值
      return float64(current)
   }

   return 0
}

总结:

  1. 循环时最多只用到当前值和上一个值。
    一开始的作法是把数组1和数组2的元素添加到另外一个切片中,结束循环的条件相同,最后再取中位数的值。
    这种方法有频繁的切片操作,耗时也耗内存。

  2. 一开始还加上了对数组1和数组2里元素个数是 0 还是 1 的判断,现在的循环已经包括这两种情况,判断画蛇添足,而且大部分的测试用例,肯定是元素个数大于 1 的,所以效率也不高。

  3. 取上一个值的地方,也走了弯路,用标志来记录上次用的是哪个数组的值。
    后来看了高手的答案后才发现,在每次循环开始的地方,把当前值的值设置给上一个值就可以了。
    又是大脑短路!囧!