美文网首页
4.寻找两个正序数组的中位数-java实现

4.寻找两个正序数组的中位数-java实现

作者: ontheway_sh | 来源:发表于2020-08-13 12:00 被阅读0次

    第四题:寻找两个正序数组的中位数

    给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
    请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
    你可以假设 nums1 和 nums2 不会同时为空。
    示例 1:

    nums1 = [1, 3]
    nums2 = [2]
    则中位数是 2.0
    

    示例 2:

    nums1 = [1, 2]
    nums2 = [3, 4]
    则中位数是 (2 + 3)/2 = 2.5
    

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/check-permutation-lcci
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    V1版本

    既然有是序的那就好办了,题目说了不会同时为空,就说明可能会有一个为空的情况
    所以可分为两种情况进行
    1,有一个数组为空的情况
    1.1 数组长度为奇数,中位数就是中间那个数
    例[1,2,3,4,5],数组长度为5,index为2,应该取出下标为2的数(3)为中位值
    1.2 数组长度为偶数,
    例[1,2,3,4],数组长度为4,index为2,应该取出下标为 1,2两个数(2,3),取平均值

    2, 两个数组都不为空
    两个数组都不为空且有序,先获取两个数据的总长度算出中位数出现的位置(总长度/2)
    例:
    num1[1,3,5],num2[2],这时总长度为4
    num1[1,3,5],num2[2,4],这时总长度为5
    不管是哪种形式,我们都是循环取两个数组中的值去比对,值更小的数组下标向后滑动一位
    最终都去获取下标为 (总长度/2)和(总长度/2 - 1) 下标的值
    如:
    第一对数组我们取出值 [2,3]
    第二对数组我们取出值 [2,3]
    由于一第组数组总长度为偶数,对我们将取这两个数的平均值(2.5)进行返回
    第二组为奇数,我们直接返回后面那个值(即3)
    注意:要考虑边界情况,小心数组越界
    代码如下:

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            /**
             * 两个数数组不会同时为空,只有一个数组的时候执行效率更高
             */
            if (nums1 == null || nums1.length == 0) {
                return findMedianSortedArrays(nums2);
            }
            if (nums2 == null || nums2.length == 0) {
                return findMedianSortedArrays(nums1);
            }
            // 定义两个数组初始下标值
            int numIndex1 = 0, numIndex2 = 0;
            // 总数组长度
            int totalLength = nums1.length + nums2.length;
            // 是否为奇数
            boolean isOddNumber = totalLength % 2 == 1;
            /**
             * 获取两个中位数的位置,
             * 如果是积数位,则后续直接返回endIndex
             * 如果是偶数位,后续返回两个坐标对应值的平均值
             */
            int endIndex = totalLength/2;
            int startIndex = endIndex - 1;
            int startValue = 0;
            int endValue = 0;
    
            // 临时变量
            int value;
            for (int i = 0; i <= endIndex; i++) {
                if (numIndex2 >= nums2.length) {
                    value = nums1[numIndex1];
                    numIndex1++;
                } else if (numIndex1 >= nums1.length) {
                    value = nums2[numIndex2];
                    numIndex2++;
                } else if (nums1[numIndex1] < nums2[numIndex2]) {
                    value = nums1[numIndex1];
                    numIndex1++;
                } else {
                    value = nums2[numIndex2];
                    numIndex2++;
                }
    
                if (i == startIndex) {
                    startValue = value;
                } else if (i == endIndex) {
                    endValue = value;
                }
            }
            return isOddNumber? endValue : getAverage(startValue, endValue);
        }
    
        /**
         * 有一条数组为空的情况
         */
        public double findMedianSortedArrays(int[] nums) {
            int index = nums.length / 2;
            /**
             * 数组长度为奇数,中位数就是中间那个数
             * 例[1,2,3,4,5],数组长度为5,index为2,应该取出下标为2的数(3)为中位值
             */
            if (nums.length % 2 == 1) {
                return nums[index];
            }
            /**
             * 数组长度为偶数,
             * 例[1,2,3,4],数组长度为4,index为2,应该取出下标为 1,2两个数(2,3),取平均值
             */
            return getAverage(nums[index - 1], nums[index]);
        }
    
        /**
         * 获取平均值
         */
        private static double getAverage(int a, int b) {
            return ((double)a + (double)b) / 2;
        }
    

    这道题是让我困惑的是难度竟然是:困难,但是出奇的好实现不过我的实现代码很长,在去看看大佬们的实现思路


    image.png

    V2版本

    去看了一下官方的实现,由于官方的在数组总长度为偶数时,去遍历了两次来获取结果,我认为这种方式还是不可取


    image.png

    V2版本想继续优化的点就是在两个数组极不平衡的时候
    例:num1[1,3,4,5,7,9,11,13,15,17,19,.....],num2[2]
    的时候,其实不需要继续向下循环,可以快速的获取结果,不过代码实现可能会更复杂,可读性会变差,
    暂时没有好的方式实现,V2版本先暂停

    相关文章

      网友评论

          本文标题:4.寻找两个正序数组的中位数-java实现

          本文链接:https://www.haomeiwen.com/subject/qqsbdktx.html