zoukankan      html  css  js  c++  java
  • 4. 寻找两个有序数组的中位数

    题目

    1. 中文题目

      中文题目

    2. 英文题目

      英文题目

    分析

    1. 先要确定中位数是第几个数,两个数组中数一共有n个,则中位数为第 (frac{n+1}{2}) (n为奇数),第 (frac{n+1}{2})(frac{n+1}{2}+1) 的平均数个(n为偶数). 所以我们先找出第 (frac{n+1}{2}) 个数就很容易求出中位数了;
    2. 找中位数我们只需将数组分成两部分, 一侧的每一个数都比另一侧大. 且有一侧的个数刚好是(frac{n+1}{2}), 中位数就在我们分割的切口处;
    3. 时间复杂度要求为O(log(m+n)), 所以我们在找分割处时要使用二分法;
    4. 分割有多钟情况, 且需要注意极限情况;

    正确代码

    错误代码

    1. 没有使用二分法导致时间复杂度很高且超出数组边界

    class Solution {
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
           int medianFirst = (nums1.length + nums2.length + 1)/2;
            int aLeft = (nums1.length)/2 - 1;
            int bLeft = medianFirst - aLeft - 2;
            double median1;
            while(true){
                if(nums1[aLeft] > nums2[bLeft+1]){
                    aLeft--;
                    bLeft++;
                }else if (nums2[bLeft] > nums1[aLeft+1]){
                    aLeft++;
                    bLeft--;
                }else break;
            }
            median1 = Math.max(nums1[aLeft], nums2[bLeft]);
            if((nums1.length+nums2.length)%2!=0)
                return median1;
            else {
                return (median1 + Math.min(nums1[aLeft + 1], nums2[bLeft + 1])) / 2;
            }
        }  
    }
    

    测试用例为[1, 3], [2]

    正确代码

    class Solution {
        public static void main(String[] args) {
            int[] nums1 = {3};
            int[] nums2 = {-2, -1};
    
            double result = findMedianSortedArrays(nums1, nums2);
            System.out.println(result);
        }
        public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
            //确保第一个数组长度更短
            if(nums1.length > nums2.length){
                return findMedianSortedArrays(nums2, nums1);
            }
            int length1 = nums1.length;
            int length2 = nums2.length;
            int totleLength = length1 + length2;
            //第一个中位数是排在第几的数
            int firstMI = (totleLength + 1) / 2;
            //二分法
            int left = 0;
            int right = length1;
            int line1;
            int line2;
            int left1;
            int right1;
            int left2;
            int right2;
            while(true){
                //第一个数组划分区域右边
                line1 = (left + right)/2;
                //第二个数组划分区域右边
                line2 = firstMI-line1;
                //检查数组越界的问题
                //第一个数组的左数
                left1 = line1 <=0 ? Integer.MIN_VALUE : nums1[line1-1];
                //第一个数组的右数
                right1 = line1 >= length1 ? Integer.MAX_VALUE : nums1[line1];
                //第二个数组的左数
                left2 = line2 <=0 ? Integer.MIN_VALUE : nums2[line2-1];
                //第一个数组的右数
                right2 = line2 >= length2 ? Integer.MAX_VALUE : nums2[line2];
                if(right1 < left2){
                    //往右取值
                    left = line1+1;            
                }else if(left1 > right2){
                    //往左取值
                    right = line1-1;
                }else{
                    break;
                }
            }
            //第一个中位数
            int firstM = Math.max(left1, left2);
            //中位数
            double m = totleLength%2 == 0 ? ( firstM+Math.min(right1, right2) )/2.0 : firstM;
            return m;
        }
    }
    
  • 相关阅读:
    会场安排
    Comet OJ
    CodeForces1154F
    CodeForces1154E
    2019.08.25校内模拟赛Graph
    2019.08.25校内模拟赛Page
    [MtOI2019]灵梦的计算器
    [MtOI2019]永夜的报应
    [NOI2018]归程
    USACO[CowCoupons]
  • 原文地址:https://www.cnblogs.com/karlshuyuan/p/14633561.html
Copyright © 2011-2022 走看看