多数组中位数

来源:互联网 发布:linux 复制粘贴文件 编辑:程序博客网 时间:2024/05/16 15:48

题目:
给定两个有序数组arr1和arr2,两个数组长度都为N,求两个数组中所有数的上中位数。
例如:
arr1 = {1,2,3,4};
arr2 = {3,4,5,6};
一共8个数则上中位数是第4个数,所以返回3。
arr1 = {0,1,2};
arr2 = {3,4,5};
一共6个数则上中位数是第3个数,所以返回2。
要求:时间复杂度O(logN)

解析:
1. 首先需要理解什么叫做上中位数,其实很简单,两个数组整合,必然是偶数项,中位数是一个小数,所以,上中位数,表示较小的一方,也就是n/2的向下取整。
2. 因为有log在时间复杂度里面,所以一定要使用二分查找。
3. 首先取二者的中位数,在O(1)时间复杂度内求出,那么数组arr1的midValue = 2,数组arr2的midValue = 4,则较小的元素midValue的左边所有元素,也就是midPosition个,和较大元素右边的所有元素,都要去掉,由于去掉的元素占所有元素的一 半,所以复杂度为O(logn)。只需要移动Lindex和Rindex的位置即可,直到 Lindex == Rindex - 1

代码:

public class Solution {    public int getUpMedian(int[] arr1, int[] arr2) {        // 使用二分法来解决问题        // 确定要查找的范围        int L1=0;        int R1=arr1.length-1;        int L2=0;        int R2=arr2.length-1;        // 涉及到复杂度的情况,千万不要使用for循环        while(L1<R1 && L2<R2){            int mid1=(L1+R1)/2;            int mid2=(L2+R2)/2;            // 折半,选择中间结点进行比较,如果相等,则直接返回            if(arr1[mid1]==arr2[mid2]){                return arr1[mid1];            }            // 如果前者大,那么继续while循环,说明中位数在后者,更新值            if(arr1[mid1]>arr2[mid2]){                // 重新更新点,大的一方要更新右侧,小的一方要更新左侧                // 左侧更新原则:因为考虑到logN,所以要进行优化                mid2=((L2+R2)%2==0)?mid2:(mid2+1);                R1=mid1;                L2=mid2;            }else{                mid1=((L1+R1)%2==0)?mid1:(mid1+1);                L1=mid1;                R2=mid2;            }        }        // 返回结果        return (arr1[L1] > arr2[L2]) ? arr2[L2] : arr1[L1];    }}
原创粉丝点击