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

    翻译一下:有两个分别排好序的数组num1和num2,大小分别为m和n。找到这两个数组合并后的中位数。时间复杂度应该为O(log(m+n))。

    第一种解法:方法是首先排好序(排序只需要排到一半),然后找到中位数。

    package com.test;
    
    public class Median {
        
        @org.junit.Test
        public void test(){
            int[] a = {1,4,6};
            int[] b = {2,6,8};
            System.out.println( "中位数为" + getMedian(a,b));
        }
        
        public double getMedian(int[] arrayA,int[] arrayB){
            int lengthA = arrayA.length;
            int lengthB = arrayB.length;
            int halfLength = (lengthA + lengthB) / 2 + 1;
            int[] newArray = new int[halfLength];
            int i = 0,j = 0,k = 0;
            while( i < lengthA && j < lengthB && k < halfLength){
                if(arrayA[i] <= arrayB[j]){
                    newArray[k++] = arrayA[i++];
                }else{
                    newArray[k++] = arrayB[j++];
                }
            }
            while(i < lengthA && k < halfLength){
                newArray[k++] = arrayA[i++];
            }
            while(j < lengthB && k < halfLength){
                newArray[k++] = arrayB[j++];
            }
            if((lengthA + lengthB) % 2 == 0){
                return ((double)newArray[k-1] + (double)newArray[k-2])/2;
            }else{
                return (double)(newArray[k-1]);
            }
        }
    }

    时间复杂度:O((m+n)/2) = O(m+n)。

    空间复杂度:O((m+n)/2) = O(m+n)。

    第二种解法:

    首先我们用一个随机数 i 将数组A分成两部分:

    既然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_A和left_B放在左边,然后把right_A和right_B放到另一边,我们起名叫left_part和right_part。

     

    只要我们把{A,B}分成相等的两部分,并且其中一部分比另一部分大。那么就有

    为了确保这两个条件,我们只需要确保

     

    注意1:为简单起见,我们假定即使当i = 0,i = m,j = 0,j = n时A[i-1],B[J-1],A[i],B[j]都是合法的。我们在最后在讨论如何处理这些边界值。

    注意2:为什么n >= m ?因为我们必须确保 j 是非负的。如果n < m,j也许是负数,这将导致错误的结果。

    接下来需要做的是:

    package com.test;
    
    public class Median {
        
        @org.junit.Test
        public void test(){
            int[] a = {1,4,6};
            int[] b = {2,6,8};
            System.out.println( "中位数为" + findMedianSortedArrays(a,b));
        }
        
        public double findMedianSortedArrays(int[] A, int[] B) {
            int m = A.length;
            int n = B.length;
            if (m > n) { // to ensure m<=n
                int[] temp = A; A = B; B = temp;
                int tmp = m; m = n; n = tmp;
            }
            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 && B[j-1] > A[i]){
                    iMin = iMin + 1; // i is too small
                }
                else if (i > iMin && A[i-1] > B[j]) {
                    iMax = iMax - 1; // i is too big
                }
                else { // i is perfect
                    int maxLeft = 0;
                    if (i == 0) { maxLeft = B[j-1]; }
                    else if (j == 0) { maxLeft = A[i-1]; }
                    else { maxLeft = Math.max(A[i-1], B[j-1]); }
                    if ( (m + n) % 2 == 1 ) { return maxLeft; }
    
                    int minRight = 0;
                    if (i == m) { minRight = B[j]; }
                    else if (j == n) { minRight = A[i]; }
                    else { minRight = Math.min(B[j], A[i]); }
    
                    return (maxLeft + minRight) / 2.0;
                }
            }
            return 0.0;
        }
    }

    结果:

     

     时间复杂度:O(log(min(m,n)))。最开始,查找的范围是[0,m]。并且每次循环查找的范围都会少一半,因此,我们仅仅需要log(m)次循环。每次循环都是常量级操作,因此时间复杂度为O(log(m))。又因为m <= n,因此时间复杂度为O(log(min(m,n)))。

    空间复杂度:O(1)。

    身体是革命的本钱,爱跑步,爱生活!
  • 相关阅读:
    JQuery替换空字符串和正则表达式校验时间格式
    数据库升级,给某张表增加字段,防止重复升级时sql脚本报错
    将jar包安装到本地repository中
    springCloud集成常用组件(持续更新)
    记一次springboot配置事务@transactional失效的事故
    分布式锁实现(Redis和zookeeper)
    springCloud集成zookeper
    zookeeper学习相关
    springboot集成activeMq
    springboot集成redis
  • 原文地址:https://www.cnblogs.com/caozx/p/8639729.html
Copyright © 2011-2022 走看看