68.寻找两个正序数组的中位数

39 阅读2分钟

题目链接

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

解法 二分查找

思路

既然题目要求了空间复杂度,那么暴力解法肯定不行,暴力解法就是合并数组然后返回中位数,时间复杂度是 O(m+n)

那么只能采用二分的方法,这道题又不像之前的二分题目,套用模板即可。而是采取一些思维上的变通。题目要找到两个有序数组的中位数,我们先假设两个数组一样长,可以通过找到第 k 小的数来获取他们的中位数。因为他们是有序数组嘛,假设这个数组长度 3 ,第 2 小的数是不是就是它的中位数,当然实际操作中索引还是要减 1

这个道理同样运用到两个数组当中,如果比较了这两个数组的第 k 小的数,小的那一边的数组都不符合,因为都比较小,所以可以不纳入考虑,此时我们更新 k 继续迭代即可。

代码

function findMedianSortedArrays(nums1: number[], nums2: number[]): number {
    const findKthSmall = (arr1, arr2, k) => {
        let index1 = 0;
        let index2 = 0;

        while (true) {
            if (index1 === arr1.length) {
                return arr2[index2 + k - 1];
            }
            if (index2 === arr2.length) {
                return arr1[index1 + k - 1];
            }
            if (k === 1) {
                return Math.min(arr1[index1], arr2[index2]);
            }

            // 正常二分逻辑
            const half = Math.floor(k / 2);
            const newIndex1 = Math.min(index1 + half, arr1.length) - 1;
            const newIndex2 = Math.min(index2 + half, arr2.length) - 1;

            const pivot1 = arr1[newIndex1];
            const pivot2 = arr2[newIndex2];

            if (pivot1 <= pivot2) {
                k -= (newIndex1 - index1 + 1);
                index1 = newIndex1 + 1;
            } else {
                k -= (newIndex2 - index2 + 1);
                index2 = newIndex2 + 1;
            }
        }
    };
    const totalLength = nums1.length + nums2.length;

    if (totalLength % 2 === 1) {
        return findKthSmall(nums1, nums2, Math.floor(totalLength / 2) + 1);
    } else {
        const mid1 = findKthSmall(nums1, nums2, totalLength / 2);
        const mid2 = findKthSmall(nums1, nums2, totalLength / 2 + 1);
        return (mid1 + mid2) / 2;
    }
};

时空复杂度

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

空间复杂度:O(1)