LeetCode Median of Two Sorted Arrays

来源:互联网 发布:c语言打印倒直角三角形 编辑:程序博客网 时间:2024/05/16 12:09

问题网址:https://leetcode.com/problems/median-of-two-sorted-arrays/description/

问题描述:
给定两个有序数组nums1和nums2大小分别为m和n。
找到两个有序数组的中位数。 整体运行时间复杂度应为O(log(m + n))。

问题样例:
Example 1:

nums1 = [1, 3]nums2 = [2]The median is 2.0

Example 2:

nums1 = [1, 2]nums2 = [3, 4]The median is (2 + 3)/2 = 2.5

一个简单想法:
学过归并排序的同学显然知道这是一个归并的过程

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {    vector<int> a;    int i = 0, j = 0;    while (i < nums1.size() && j < nums2.size()) {        if (nums1[i] <= nums2[j])            a.push_back(nums1[i++]);        else            a.push_back(nums2[j++]);    }    while (i < nums1.size())        a.push_back(nums1[i++]);    while (j < nums2.size())        a.push_back(nums2[j++]);    if (a.size() % 2)        return a[a.size() / 2];    else        return (a[a.size() / 2 - 1] + a[a.size() / 2]) / 2.0;}

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

改进的想法:
为了解决这个问题,我们需要了解“中位数的应用”。 统计学中,中位数用于:
将集合划分为两个相等长度的子集,一个子集总是大于另一子集。
如果我们了解中位数的使用,我们非常接近答案。
首先让我们将A随机分为两部分:

          left_A             |        right_A    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]

由于A有m个元素,所以有m + 1种分法(i = 0~m)。
我们知道:

len(left_A) = i, len(right_A) = m−i.i = 0, left_A 为空, 当 i = m, right_A 为空.

以相同的方式将B在随机分成两部分:

          left_B             |        right_B    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

将left_A和left_B放入一个集合,并将right_A和right_B放入另一集合。 我们把它们命名为left_part和right_part:

          left_part          |        right_part    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

如果我们能确保:

1. len(left_part)=len(right_part)2. max(left_part)≤min(right_part)

那么我们将{A,B}中的所有元素分成两个等长的部分,一部分总是大于另一部分。 然后
median = (max(left_part) + min(right_part)) / 2
为了确保这两个条件,我们只需要确保:

i + j = m − i + n − j (or: m - i + n - j + 1)如果 n ≥ m, 令 i = 0∼m, j = (m+n+1)/2i
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {    if (nums1.size() > nums2.size())        swap(nums1, nums2);    int m = nums1.size();    int n = nums2.size();    int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;    while (iMin <= iMax) {        int i = (iMin + iMax) / 2;        int j = halfLen - i;        if (i < iMax && nums2[j-1] > nums1[i])            iMin++;        else if (i > iMin && nums1[i-1] > nums2[j])            iMax--;        else {            int maxLeft = 0;            if (i == 0)                maxLeft = nums2[j-1];            else if (j == 0)                maxLeft = nums1[i-1];            else                maxLeft = max(nums1[i-1], nums2[j-1]);            if ((m+n) % 2 == 1)                return maxLeft;            int minRight = 0;            if (i == m)                minRight = nums2[j];            else if (j == n)                minRight = nums1[i];            else                minRight = min(nums2[j], nums1[i]);            return (maxLeft + minRight) / 2.0;        }    }    return 0.0;}

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

原创粉丝点击