Last Commit: 2024-01-06 17:50:27

views:

4. Median of Two Sorted Arrays

source: https://leetcode.com/problems/median-of-two-sorted-arrays/

Question

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

The overall run time complexity should be O(log (m+n)).

初想法

如果使用已有的sort函数,看v8的代码:

在数组长度小于等于10时是用插入排序,大于10是用快速排序。

这里我们先只考虑快速排序,那么平均状况下时间复杂度是O(nlogn),和题目要求的O(logn)相比还是有差距的。

var findMedianSortedArrays = function (nums1, nums2) {
  const arr = [...nums1, ...nums2].sort((a, b) => a - b);
  return arr.length % 2 === 1
    ? arr[(arr.length - 1) / 2]
    : (arr[Math.floor((arr.length - 1) / 2)] +
        arr[Math.ceil((arr.length - 1) / 2)]) /
        2;
};

二分查找

这里有一个很重要的前提条件,这两个数组是sorted的。

在此前提下,每次找k/2个元素,根据两个数组k/2位置元素的大小,就可以排除k/2个元素,然后一步步找到第k个元素。

时间复杂度是O(log(m+n)).

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function (nums1, nums2) {
  /**
   * 找到两个sorted arrays的排序为k的元素
   */
  const getKthElement = (k) => {
    const len1 = nums1.length;
    const len2 = nums2.length;
    let index1 = 0;
    let index2 = 0;
    while (true) {
      if (index1 === len1) {
        // * nums1 到头了
        return nums2[index2 + k - 1];
      } else if (index2 === len2) {
        // * nums2 到头了
        return nums1[index1 + k - 1];
      } else if (k === 1) {
        // * 最后一次比较
        return Math.min(nums1[index1], nums2[index2]);
      }

      const half = k >> 1; // JS 中 k/2 不是整除,可以用parseInt(k/2)代替
      let newIndex1 = Math.min(index1 + half - 1, len1 - 1); // * 要注意index1+half-1可能会越界溢出, 所以下标最大为len1-1
      let newIndex2 = Math.min(index2 + half - 1, len2 - 1); // 同上

      if (nums1[newIndex1] <= nums2[newIndex2]) {
        // * 开始抛弃部分序列,更新K值,抛弃的长度为newIndex1 - index1 + 1,对应end-start+1
        k -= newIndex1 - index1 + 1;
        index1 = newIndex1 + 1; // * 更新抛弃过的序列的下标
      } else {
        // 同上
        k -= newIndex2 - index2 + 1;
        index2 = newIndex2 + 1;
      }
    }
  };
  const totalLength = nums1.length + nums2.length;
  const median = totalLength >> 1;
  // * 核心思路为, 用二分找到从小到大第K个数
  if (totalLength % 2 === 1) {
    return getKthElement(median + 1);
  } else {
    return (getKthElement(median) + getKthElement(median + 1)) / 2;
  }
};

End

O(logn)的复杂度可以优先想到二分查找。