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


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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    private int findKth(int[] num1, int[] num2, int k) {
        if (num1.length == 0) {
            return num2[k - 1];
        }

        if (num2.length == 0) {
            return num1[k - 1];
        }

        int[] shortArray = num1.length < num2.length ? num1 : num2;
        int[] longArray = shortArray == num1 ? num2 : num1;

        if (k <= shortArray.length) {
            return findUpMedian(shortArray, 0, k - 1, longArray, 0, k - 1);
        } else if (k <= longArray.length) {
            // 1 2 3 4 5
            // 1 [2 3 4 5 6 [7]] 8 9
            int longStart = k - shortArray.length - 1;
            if (longArray[longStart] >= shortArray[shortArray.length - 1]) {
                return longArray[longStart];
            }
            return findUpMedian(shortArray, 0, shortArray.length - 1, longArray, longStart + 1, k - 1);
        } else {
            // 1 2 [3 4 5]
            // 1 2 3 4 [5 6 7] | 8 9 [10] 11 12
            int shortStart = k - longArray.length - 1;
            int longStart = k - shortArray.length - 1;
            if (shortArray[shortStart] >= longArray[longArray.length - 1]) {
                return shortArray[shortStart];
            }

            if (longArray[longStart] >= shortArray[shortArray.length - 1]) {
                return longArray[longStart];
            }

            return findUpMedian(shortArray, shortStart + 1, shortArray.length - 1, longArray, longStart + 1, longArray.length - 1);
        }
    }

    /**
     * 发现两个等长增序数组的中位数
     */
    private int findUpMedian(int[] num1, int start1, int end1, int[] num2, int start2, int end2) {
        while (start1 < end1) {
            int m1 = (start1 + end1) >> 1;
            int m2 = (start2 + end2) >> 1;
            int offset = (end1 - start1 + 1) & 1 ^ 1;

            // 1 2 3 4 5
            // 1 2 3 4 5

            // 1 2 3 4 5 6
            // 1 2 3 4 5 6
            if (num1[m1] < num2[m2]) {
                start1 = m1 + offset;
                end2 = m2;
            } else {
                start2 = m2 + offset;
                end1 = m1;
            }
        }
        return Math.min(num1[start1], num2[start2]);
    }

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int length = (nums1.length + nums2.length);

        if (length % 2 == 0) {
            return (findKth(nums1, nums2, length / 2) + findKth(nums1, nums2, length / 2 + 1)) / 2.0;
        } else {
            return findKth(nums1, nums2, length / 2 + 1);
        }
    }
}

相关