zoukankan      html  css  js  c++  java
  • 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);
            }
    
        }
    }
    

      

     



  • 相关阅读:
    Linux常用命令及示例(全)
    linux下安装配置svn服务器
    Kafka、Redis和其它消息组件比较
    ORACLE定时备份方案
    mysql库表优化实例
    携程apollp快速部署DVE集群
    windows 安装Zookeeper 配置集群
    Ubuntu 18.04 LTS 修改Host,使用Host访问
    PowerShell因为在此系统中禁止执行脚本......
    常用第三方工具的Docker命令
  • 原文地址:https://www.cnblogs.com/superzhaochao/p/6380137.html
Copyright © 2011-2022 走看看