Question 2 of leetcode, median of two sorted Arrays

Source: Internet
Author: User
Questions Reproduction

There are two sorted arrays A and B of size M and N respectively. find the median of the two sorted arrays. the overall run time complexity shoshould be O (log (m + n )).

It means to give two ordered arrays (m, n may be 0) of M and N, and to find the median of these two arrays. and the time complexity of the program must not exceed O (log (m + n )). this question gives me the first feeling that it is not difficult, but it requires complexity. at the same time, the most direct method is to combine the two arrays into an ordered array, and then directly find the median. how to merge two ordered arrays? (This topic is worth studying. Check the information later .) first, apply for an array space of m + n, copy the two arrays into the space, and then use the sort function to sort the space, and then directly look for the output. the Code is as follows:
class Solution {public:    double findMedianSortedArrays(int A[], int m, int B[], int n) {        // Start typing your C/C++ solution below        // DO NOT write int main() function        int *a=new int[m+n];                memcpy(a,A,sizeof(int)*m);        memcpy(a+m,B,sizeof(int)*n);                sort(a,a+n+m);                double median=(double) ((n+m)%2? a[(n+m)>>1]:(a[(n+m-1)>>1]+a[(n+m)>>1])/2.0);                delete a;                return median;    }};

What I didn't expect was that I passed .................... I think I am cheating, and the time complexity has not reached the requirement O (m + n )......................... this is all done .................. orz.

The Python code of this method is also very easy to write. However, it seems that leetcode does not support the python built-in method, because when I use the sorted function, it is not possible to compile it .......

Then there is the second solution. We can find that we do not need to "sort" such complex operations now, because we only need the K-level elements. We can use a counter to record the elements that are currently located at the MB level. At the same time, we use two pointers, Pa and Pb, pointing to the first element of the and B arrays respectively. The principle similar to merge sort is used. If the current element of array a is small, then PA ++ and M ++ are used at the same time. If the current element of array B is small, Pb ++ and M ++ are used at the same time. When M is equal to K, we get our answer-O (k) time, O (1) space.
The test code is as follows:
#include <iostream>#include <vector>#include <algorithm>using namespace std;class Solution{private:double findKth(int a[], int m, int b[], int n, int k){int i = 0;int j = 0;int index = 1;int kth;if (m == 0)return b[k-1];if (n == 0)return a[k-1];if (k ==1)return a[0]>b[0] ? b[0] : a[0];        if (k == 2)            return (a[0] + b[0]) /2.0;while(index <= k && i < m && j < n){if( a[i] >= b[j]){index ++;kth = b[j];j ++;}else{index ++;kth = a[i];i ++;}}if( index < k && j == n)        {            kth = a[i+k-index];        }        if (index < k && i == m)            kth = b[j+k-index];return kth;}public:double findMedianSortedArrays(int A[], int m, int B[], int n){int total = m + n;// totla is even OR odd ?if (total & 0x1)           // evenreturn findKth(A, m, B, n, total / 2 + 1);else   // oddreturn (findKth(A, m, B, n, total / 2)+ findKth(A, m, B, n, total / 2 + 1)) / 2;}};int main(){Solution s1;int A[] = {6,7,8,9};int B[] = {5,6};cout << s1.findMedianSortedArrays(A, 4, B, 2) << endl;return 0;}



However, in leetcode, the same results as those in the test are not obtained ............. Then there is a sharp method: You can consider starting with K. If we can remove an element that must be before the k-th element every time, we need to perform K times. But what if we get rid of half each time? So with this idea similar to binary, we can consider the following: (from others)
Assume that the number of elements in A and B are both larger than K/2, and if we compare the k/2-th smallest element in a (I. e. A [k/2-1]) and the k-th smallest element in B (I. e. B [k/2-1]), there are three results:
(Becasue K can be odd or even number, so we assume K is even number here for simplicy. The following is also true when K is an odd number .)
A [k/2-1] = B [k/2-1]
A [k/2-1]> B [k/2-1]
A [k/2-1] <B [k/2-1]
If a [k/2-1] <B [k/2-1], that means all the elements from a [0] to a [k/2-1] (I. e. the k/2 smallest elements in a) are in the range of K smallest elements in the Union of A and B. or, in the other word, a [k/2-1] can never be larger than the k-th smalleset element in the Union of A and B.

Why?
We can use a proof by contradiction. since a [k/2-1] is larger than the k-th smallest element in the Union of A and B, then we assume it is the (k + 1) -Th smallest one. since it is smaller than B [k/2-1], then B [k/2-1] shocould be at least the (K + 2)-th smallest one. so there are at most (K/2-1) elements smaller than a [k/2-1] In a, and at most (K/2-1) elements smaller than a [k/2-1] in B. so the total number is k/2 + k/2-2, which, no matter when K is odd or even, is surly smaller than K (since a [k/2-1] is the (k + 1)-th smallest element ). so a [k/2-1] can never larger than the k-th smallest element in the Union of A and B if a [k/2-1] <B [k/ 2-1];
Since there is such an important conclusion, we can safely drop the first K/2 element in A, which are definitaly smaller than k-th element in the Union of A and B. this is also true for the [k/2-1]> B [k/2-1] condition, which we shoshould drop the elements in B.
When a [k/2-1] = B [k/2-1], then we have found the k-th smallest element, that is the equal element, we can call it m. there are each (K/2-1) numbers smaller than m in A and B, so m must be the k-th smallest number. so we can call a function recursively, when a [k/2-1] <B [k/2-1], we drop the elements in, else we drop the elements in B.


We shoshould also consider the edge case, that is, when shoshould we stop?
1. When A or B is empty, we return B [k-1] (or a [k-1]), respectively;
2. When k is 1 (when A and B are both not empty), we return the smaller one of a [0] and B [0]
3. When a [k/2-1] = B [k/2-1], we shoshould return one of them

In the code, we check if M is larger than N to garentee that the we always know the smaller array, for coding simplicy.
double findKth(int a[], int m, int b[], int n, int k){//always assume that m is equal or smaller than nif (m > n)return findKth(b, n, a, m, k);if (m == 0)return b[k - 1];if (k == 1)return min(a[0], b[0]);//divide k into two partsint pa = min(k / 2, m), pb = k - pa;if (a[pa - 1] < b[pb - 1])return findKth(a + pa, m - pa, b, n, k - pa);else if (a[pa - 1] > b[pb - 1])return findKth(a, m, b + pb, n - pb, k - pb);elsereturn a[pa - 1];}class Solution{public:double findMedianSortedArrays(int A[], int m, int B[], int n){int total = m + n;if (total & 0x1)return findKth(A, m, B, n, total / 2 + 1);elsereturn (findKth(A, m, B, n, total / 2)+ findKth(A, m, B, n, total / 2 + 1)) / 2;}};

Another method: first convert to the problem of finding the number of K smaller values in array A and array B, and then use k/2 to find them in array A and array B. For example, K = 6 is used to view the 3rd numbers in A and B respectively. A1 <A2 <A3 <A4 <a5... and B1 <b2 <B3 <B4 <b5 ..., if A3 <= B3, then the 6th smaller number is definitely not A1, A2, A3, because up to two numbers are smaller than A1, three are smaller than A2, and four are smaller than A3. B3 must have at least five numbers, so the 6th small number may be B1 (A1 <A2 <A3 <A4 <A5 <B1 ), it may be B2 (A1 <A2 <A3 <B1 <A4 <B2), or B3 (A1 <A2 <A3 <B1 <b2 <B3 ). Then we can exclude A1, A2, A3, and convert them into A4, A5 ,... b1, B2, B3 ,... K is halved when the number is 3rd small. Each time we assume that A has a small number of elements, and the results of Pa = min (K/2, Lena) may lead to k = 1 or a null. Both conditions are termination conditions.

class Solution:    # @return a float         def getMedian(self, A, B, k):        # return kth smallest number of arrays A and B, assume len(A) <= len(B)        lenA = len(A); lenB = len(B)        if lenA > lenB: return self.getMedian(B, A, k)        if lenA == 0: return B[k-1]        if k == 1: return min(A[0], B[0])        pa = min(k/2, lenA); pb = k - pa        return self.getMedian(A[pa:], B, k - pa) if A[pa - 1] <= B[pb - 1] else self.getMedian(A, B[pb:], k - pb)         def findMedianSortedArrays(self, A, B):        lenA = len(A); lenB = len(B)        if (lenA + lenB) % 2 == 1:             return self.getMedian(A, B, (lenA + lenB) / 2 + 1)        else:            return 0.5 * ( self.getMedian(A, B, (lenA + lenB) / 2) + self.getMedian(A, B, (lenA + lenB) / 2 + 1) )

.............. This question is not easy ....

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.