Median of Two sorted Arrays

这是一道属于quick select的变种类型题,和quick select不同的是数组已经排好序且数组有两个,我们要找的是两个数组合并之后的中位数,这里最关键的一点就是要发现找第k个数的时候,有一个关键的前提即如果A[k / 2 - 1] < B[k / 2 - 1]则表示,A的前k/2数必然是在前k个里面的,我们可以直接把这个k/2个数砍掉,反之亦然,有了这个前提就相当于我们可以把O(k)的问题转化为一个O(k/2)的问题且只用O(1)的时间,泛化到整个数组也就是O(lgn)的总时间复杂度了,下面是代码

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        n, m = len(nums1), len(nums2)
        if (n + m) % 2:
            return self.findKth(nums1, 0, nums2, 0, (n + m) / 2 + 1)
        return (self.findKth(nums1, 0, nums2, 0, (n + m) / 2 + 1) +
                self.findKth(nums1, 0, nums2, 0, (n + m) / 2)) / 2.0

    def findKth(self, A, startA, B, startB, k):
        if startA >= len(A):
            return B[startB + k - 1]
        if startB >= len(B):
            return A[startA + k - 1]
        if k == 1:
            return min(A[startA], B[startB])
        A_key = A[startA + k / 2 - 1] if startA + k / 2 - 1 < len(A) else sys.maxint
        B_key = B[startB + k / 2 - 1] if startB + k / 2 - 1 < len(B) else sys.maxint 

        if A_key < B_key:
            return self.findKth(A, startA + k / 2, B, startB, k - k / 2)
        return self.findKth(A, startA, B, startB + k / 2, k - k / 2)

Java版本

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int m = nums2.length;
        if ((n + m) % 2 == 1) {
            return findKth(nums1, 0, nums2, 0, (n + m) / 2 + 1);
        }
        return (findKth(nums1, 0, nums2, 0, (n + m) / 2 + 1) + 
                findKth(nums1, 0, nums2, 0, (n + m) / 2)) / 2.0;
    }

    private int findKth(int[] numsA, int startA, int[] numsB, int startB, int k) {
        if (startA >= numsA.length) {
            return numsB[startB + k - 1];
        }
        if (startB >= numsB.length) {
            return numsA[startA + k - 1];
        }
        if (k == 1) {
            return Math.min(numsA[startA], numsB[startB]);
        }
        int baseA = Integer.MAX_VALUE;
        int baseB = Integer.MAX_VALUE;
        if (startA + k / 2 - 1 < numsA.length) {
            baseA = numsA[startA + k / 2 - 1];
        }
        if (startB + k / 2 - 1 < numsB.length) {
            baseB = numsB[startB + k / 2 - 1];
        }

        if (baseA < baseB) {
            return findKth(numsA, startA + k / 2, numsB, startB, k - (k / 2));
        }
        return findKth(numsA, startA, numsB, startB + k / 2, k - (k / 2));
    }
}

results matching ""

    No results matching ""