zoukankan      html  css  js  c++  java
  • 有序数组中找中位数

    原文:Median of two sorted arrays

    题目:两个有序数组A和B,大小都是n,寻找这两个数组合并后的中位数。时间复杂度为O(logn)。
    中位数:如果数组的个数是奇数,那么中位数的值就是有序时处于中间的数;如果数组个数是偶数的,那么就是有序时中间两个数的平均值。

    方法一:合并时计数

    使用Merge Sort时的Merge操作,比较两个数组时候计数,当计数达到n时,就可以得到中位数,在归并的数组中,中位数为下标n-1和n的两个数的平均值。
    时间复杂度O(n)。

    #include <stdio.h>      
      
    /*  
    This function returns median of ar1[] and ar2[].     
    Assumptions in this function:     
    Both ar1[] and ar2[] are sorted arrays     
    Both have n elements  
    */  
    int getMedian(int ar1[], int ar2[], int n)   
    {  
        int i = 0;  /* Current index of i/p array ar1[] */      
        int j = 0; /* Current index of i/p array ar2[] */      
        int count;       
        int m1 = -1, m2 = -1;        
       
        /* Since there are 2n elements, median will be average of elements at index n-1 and n  
        in the array obtained after merging ar1 and ar2 */      
        for (count = 0; count <= n; count++)       
        {           
            /*Below is to handle case where all elements of ar1[] are smaller than smallest(or first) element of ar2[]*/          
            if (i == n)           
            {               
                m1 = m2;               
                m2 = ar2[0];             
                break;         
            }           
            /*Below is to handle case where all elements of ar2[] are smaller than smallest(or first) element of ar1[]*/          
            else if (j == n)           
            {      
                m1 = m2;    
                m2 = ar1[0];    
                break;          
            }          
            if (ar1[i] < ar2[j])      
            {    
                m1 = m2;  /* Store the prev median */              
                m2 = ar1[i];               
                i++;          
            }          
            else         
            {            
                m1 = m2;  /* Store the prev median */            
                m2 = ar2[j];            
                j++;         
            }      
        }        
        return (m1 + m2)/2;   
    }     
      
    /* Driver program to test above function */  
    int main()   
    {      
        int ar1[] = {1, 12, 15, 26, 38};       
        int ar2[] = {2, 13, 17, 30, 45};        
        int n1 = sizeof(ar1)/sizeof(ar1[0]);      
        int n2 = sizeof(ar2)/sizeof(ar2[0]);      
        if (n1 == n2)         
            printf("Median is %d", getMedian(ar1, ar2, n1));      
        else         
            printf("Doesn't work for arrays of unequal size");    
      
        return 0;  
    }  

    方法二:比较两个数组的中位数

    ar1[]和ar2[]为输入的数组

    算法过程:

    1.得到数组ar1和ar2的中位数m1和m2

    2.如果m1==m2,则完成,返回m1或者m2

    3.如果m1>m2,则中位数在下面两个子数组中

    a) From first element of ar1 to m1 (ar1[0...|_n/2_|])
    b) From m2 to last element of ar2 (ar2[|_n/2_|...n-1])

    4.如果m1<m2,则中位数在下面两个子数组中

    a) From m1 to last element of ar1 (ar1[|_n/2_|...n-1])
    b) From first element of ar2 to m2 (ar2[0...|_n/2_|])

    5.重复上面的过程,直到两个子数组的大小都变成2

    6.如果两个子数组的大小都变成2,使用下面的式子得到中位数:Median = (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1]))/2

    时间复杂度:O(logn)。

    #include <stdio.h>      
      
    /* Utility functions */  
    int max(int x, int y)   
    {       
        return x > y? x : y;  
    }    
      
    int min(int x, int y)  
    {     
        return x > y? y : x;   
    }  
      
    /* Function to get median of a sorted array */  
    int median(int arr[], int n)   
    {     
        if (n%2 == 0)         
            return (arr[n/2] + arr[n/2-1])/2;      
        else        
            return arr[n/2];   
    }    
      
    /*  
    This function returns median of ar1[] and ar2[].     
    Assumptions in this function:   
    Both ar1[] and ar2[] are sorted arrays    
    Both have n elements 
    */  
    int getMedian(int ar1[], int ar2[], int n)   
    {   
        int m1; /* For median of ar1 */    
        int m2; /* For median of ar2 */      
      
        /* return -1  for invalid input */   
        if (n <= 0)         
            return -1;      
        if (n == 1)        
            return (ar1[0] + ar2[0])/2;      
        if (n == 2)        
            return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2;    
      
        m1 = median(ar1, n); /* get the median of the first array */    
        m2 = median(ar2, n); /* get the median of the second array */  
            
        /* If medians are equal then return either m1 or m2 */      
        if (m1 == m2)         
            return m1;         
      
        /* if m1 < m2 then median must exist in ar1[m1....] and ar2[....m2] */    
        if (m1 < m2)    
        {         
            if (n % 2 == 0)            
                return getMedian(ar1 + n/2 - 1, ar2, n - n/2 +1);        
            else        
                return getMedian(ar1 + n/2, ar2, n - n/2);     
        }        
      
        /* if m1 > m2 then median must exist in ar1[....m1] and ar2[m2...] */      
        else     
        {      
            if (n % 2 == 0)          
                return getMedian(ar2 + n/2 - 1, ar1, n - n/2 + 1);          
            else            
                return getMedian(ar2 + n/2, ar1, n - n/2);      
        }   
    }   
      
    /* Driver program to test above function */  
    int main()   
    {      
        int ar1[] = {1, 2, 3, 6};    
        int ar2[] = {4, 6, 8, 10};    
        int n1 = sizeof(ar1)/sizeof(ar1[0]);    
        int n2 = sizeof(ar2)/sizeof(ar2[0]);      
        if (n1 == n2)      
            printf("Median is %d", getMedian(ar1, ar2, n1));     
        else      
            printf("Doesn't work for arrays of unequal size");     
      
        return 0;   
    }   

    方法三:通过二分查找法来找中位数

    基本思想是:假设ar1[i]是合并后的中位数,那么ar1[i]大于ar1[]中前i-1个数,且大于ar2[]中前j=n-i-1个数。通过ar1[i]和ar2[j]、ar2[j+1]两个数的比较,在ar1[i]的左边或者ar1[i]右边继续进行二分查找。对于两个数组 ar1[] 和ar2[], 先在 ar1[] 中做二分查找。如果在ar1[]中没找到中位数, 继续在ar2[]中查找。

    算法流程:
    1) 得到数组ar1[]最中间的数,假设下标为i.
    2) 计算对应在数组ar2[]的下标j,j = n-i-1
    3) 如果 ar1[i] >= ar2[j] and ar1[i] <= ar2[j+1],那么 ar1[i] 和 ar2[j] 就是两个中间元素,返回ar2[j] 和 ar1[i] 的平均值
    4) 如果 ar1[i] 大于 ar2[j] 和 ar2[j+1] 那么在ar1[i]的左部分做二分查找(i.e., arr[left ... i-1])
    5) 如果 ar1[i] 小于 ar2[j] 和 ar2[j+1] 那么在ar1[i]的右部分做二分查找(i.e., arr[i+1....right])
    6) 如果到达数组ar1[]的边界(left or right),则在数组ar2[]中做二分查找

    时间复杂度:O(logn)。

    #include <stdio.h>      
      
    /* A recursive function to get the median of ar1[] and ar2[] using binary search */  
    int getMedianRec(int ar1[], int ar2[], int left, int right, int n)   
    {      
        int i, j;   
      
        /* We have reached at the end (left or right) of ar1[] */    
        if(left > right)        
            return getMedianRec(ar2, ar1, 0, n-1, n);    
      
        i = (left + right)/2;      
        j = n - i - 1;  /* Index of ar2[] */      
      
        /* Recursion terminates here.*/     
        if (ar1[i] > ar2[j] && (j == n-1 || ar1[i] <= ar2[j+1]))     
        {        
            /*ar1[i] is decided as median 2, now select the median 1         
            (element just before ar1[i] in merged array) to get the average of both*/     
            if (ar2[j] > ar1[i-1] || i == 0)          
                return (ar1[i] + ar2[j])/2;        
            else            
                return (ar1[i] + ar1[i-1])/2;    
        }  
      
        /*Search in left half of ar1[]*/     
        else if (ar1[i] > ar2[j] && j != n-1 && ar1[i] > ar2[j+1])       
            return getMedianRec(ar1, ar2, left, i-1, n);     
      
        /*Search in right half of ar1[]*/      
        else /* ar1[i] is smaller than both ar2[j] and ar2[j+1]*/    
            return getMedianRec(ar1, ar2, i+1, right, n);   
    }  
      
    /*  
    This function returns median of ar1[] and ar2[].     
    Assumptions in this function:    
    Both ar1[] and ar2[] are sorted arrays   
    Both have n elements  
    */  
    int getMedian(int ar1[], int ar2[], int n)   
    {     
        // If all elements of array 1 are smaller then     
        // median is average of last element of ar1 and first element of ar2      
        if (ar1[n-1] < ar2[0])      
            return (ar1[n-1]+ar2[0])/2;       
      
        // If all elements of array 1 are smaller then       
        // median is average of first element of ar1 and       
        // last element of ar2      
        if (ar2[n-1] < ar1[0])      
            return (ar2[n-1]+ar1[0])/2;    
        
        return getMedianRec(ar1, ar2, 0, n-1, n);   
    }  
      
    /* Driver program to test above function */  
    int main()   
    {     
        int ar1[] = {1, 12, 15, 26, 38};   
        int ar2[] = {2, 13, 17, 30, 45};    
        int n1 = sizeof(ar1)/sizeof(ar1[0]);     
        int n2 = sizeof(ar2)/sizeof(ar2[0]);     
        if (n1 == n2)        
            printf("Median is %d", getMedian(ar1, ar2, n1));      
        else       
            printf("Doesn't work for arrays of unequal size");    
      
        return 0;   
    }  

    原文地址:http://www.geeksforgeeks.org/archives/2105

  • 相关阅读:
    2020-11-07:已知一个正整数数组,两个数相加等于N并且一定存在,如何找到两个数相乘最小的两个数?
    2020-11-06:go中,谈一下调度器。
    Python2和Python3中urllib库中urlencode的使用注意事项
    python爬虫基础
    python自动抢票
    Movist for Mac 1.4.2 破解版 | Mac上好用的视频播放器有哪些?7 款本地视频播放器实测对比
    前端自动化及优化
    移动端库
    jQuery
    JavaScript
  • 原文地址:https://www.cnblogs.com/luxiaoxun/p/2684054.html
Copyright © 2011-2022 走看看