leetcode : Median of two sorted arrays [难]

 

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be 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


转自: http://www.cnblogs.com/yuzhangcmu/p/4138184.html

思路: findKth 找第k大的数

 

(1)结论一:A的元素不够k/2个, 则第k大数一定不再B的前k/2中,故缩小查找范围,丢弃B的前k/2个数

反证:

假定第k大的数在B的前 k/2中,且第k大数的索引为m

=> m <= k/2 - 1 

=> A必然拥有前k个数中的  k - (m +1) 个数 . 备注: 因为数组下表从0开始

=> 因为 m <= k/2 - 1, 所以 k - (m + 1) >=  k - (k/2 - 1 + 1) = k/2

上面结论与 A元素不够 k/2矛盾,所以假设不成立。 得证。

故,在接下来的查找中,不需要查找B的前k/2个元素。

 

举个例子:

A: 6 7 8

B: 1 2 3 4 5

找第8大的数

换种思路:

 一、假定 a中所有元素小于b中所有元素,因为a的长度小于k/2, 那么 lengtha+k/2 < k.

那么元素必定不在b的前k/2中

二、假定a中所有元素大于b中所有元素。那么b中前k/2 个元素一定 小于第k大元素,故舍弃。

 

(2)结论二: A[k/2] < B[k/2], 则第k大的数一定不再A的前k/2中,故缩小查找范围,丢弃A的前k/2个数

反证: 

假定第k大的数在A的前k/2中,假设该值为maxk, 且第k大数的索引为m 

=> m <= k/2 - 1 

=> 因为两个都是有序数组,那么B必然拥有前k个数中的 k - (m + 1) 个数. 

=> 因为 m <= k/2  - 1, 则 k - (m + 1)  >= k - (k/2 - 1 + 1) = k/2

=>  k-(m +1) 个数全部小于A[k/2], 那么比B[k-(m+1)] 小的B[k/2]更是小于A[k/2]

=>  A[k/2] < B[k/2], 与题设A[k/2] < B[k/2] 矛盾,所以假设不成立,

      所有第k大的数不在A的前k/2中

 

举个例子:

A: 1 2

B: 4 5 6 7

找第四大的数,可以通过上述结论排出1,2 。把范围缩小至查找为第k/2

大的数,即找剩下两个数组的前2大的数。

 

 

package com.zhaochao.leetcode;

/**
 * Created by zhaochao on 17/2/8.
 */
public class LC04_Median_Two_Sorted_Arrays {


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

        int len1 = nums1.length;
        int len2 = nums2.length;

        if((len1 + len2) % 2 != 0 ) {
            return findKth(nums1,0,nums2,0,(len1+len2)/2 + 1);
        } else {
            return  (findKth(nums1, 0, nums2, 0, (len1 + len2) / 2) + findKth(nums1, 0, nums2, 0, (len1 + len2) / 2 + 1)) / 2;
        }
    }

    public double findKth(int[] A, int A_start, int[] B, int B_start,int k) {

        // a_start 越界
        if(A_start >= A.length) {
            return B[B_start + k - 1];
        }

        //b_start 越界
        if(B_start >= B.length) {
            return A[A_start + k - 1];
        }

        // 类似于
        if(k == 1) {
            return Math.min(A[A_start],B[B_start]);
        }

        int A_key = A_start + k / 2 - 1 < A.length ? A[A_start + k/2 - 1] : Integer.MAX_VALUE;
        int B_key = B_start + k / 2 - 1 < B.length ? B[B_start + k/2 - 1] : Integer.MAX_VALUE;

        if(A_key < B_key) {
            return findKth(A,A_start + k/2,B, B_start, k - k/2);
        } else {
            return findKth(A,A_start,B,B_start + k/2, k - k/2);
        }

    }
}

  

 



posted @ 2017-02-08 22:26  notesbuddy  阅读(171)  评论(0编辑  收藏  举报