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

问题描述:

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

方法:

划分数组

中位数:将一个集合划分为两个长度相等的子集,其中一个子集中的元素总是大于另一个子集中的元素。

因此,在任意位置i将集合A划分为两个部分有m+1种分法,同样可以在任意位置j将B划分为两个部分。

将left_A和left_B放入一个集合,并将right_A和right_B放入一个集合,分别命名为left_part和right_part。

只要保证,left_part中的元素,总小于right_part中的元素。并且i+j=(m+n+1)/2

i从0~m递增,A[i-1]递增,B[j]递减,因此总能找到满足条件的i。

时间复杂度:O(log min(m,n)) 空间复杂度:O(1)

java:

class Solution {

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {

        if (nums1.length > nums2.length) {

            return findMedianSortedArrays(nums2, nums1);

        }

        int m = nums1.length;

        int n = nums2.length;

        int left = 0, right = m, ansi = -1;

        // median1:前一部分的最大值

        // median2:后一部分的最小值

        int median1 = 0, median2 = 0;

        while (left <= right) {

            // 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]

            // 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]

            int i = (left + right) / 2;

            int j = (m + n + 1) / 2 - i;

            // nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]

            int nums_im1 = (i == 0 ? Integer.MIN_VALUE : nums1[i - 1]);

            int nums_i = (i == m ? Integer.MAX_VALUE : nums1[i]);

            int nums_jm1 = (j == 0 ? Integer.MIN_VALUE : nums2[j - 1]);

            int nums_j = (j == n ? Integer.MAX_VALUE : nums2[j]);

            if (nums_im1 <= nums_j) {

                ansi = i;

                median1 = Math.max(nums_im1, nums_jm1);

                median2 = Math.min(nums_i, nums_j);

                left = i + 1;

            }

            else {

                right = i - 1;

            }

        }

        return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;

    }

}

python:

class Solution:

    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:

        if len(nums1) > len(nums2):

            return self.findMedianSortedArrays(nums2, nums1)

        infinty = 2**40

        m, n = len(nums1), len(nums2)

        left, right, ansi = 0, m, -1

        # median1:前一部分的最大值

        # median2:后一部分的最小值

        median1, median2 = 0, 0

        while left <= right:

            # 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]

            # // 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]

            i = (left + right) // 2

            j = (m + n + 1) // 2 - i

            # nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]

            nums_im1 = (-infinty if i == 0 else nums1[i - 1])

            nums_i = (infinty if i == m else nums1[i])

            nums_jm1 = (-infinty if j == 0 else nums2[j - 1])

            nums_j = (infinty if j == n else nums2[j])

            if nums_im1 <= nums_j:

                ansi = i

                median1, median2 = max(nums_im1, nums_jm1), min(nums_i, nums_j)

                left = i + 1

            else:

                right = i - 1

        return (median1 + median2) / 2 if (m + n) % 2 == 0 else median1

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。