• 【LeetCode】【数组】【二分】4. 寻找两个正序数组的中位数 Java实现(四种方案,目前写了两种,还在更新)



    题目链接

    https://leetcode.cn/problems/median-of-two-sorted-arrays/

    题目

    在这里插入图片描述

    我的思路

    归并排序的思想,因为nums1和nums2已经是有序的,所以把两个数组中的结果放到一个新的数组中,检查index是否已经指向中位数的位置,如果是的话,在根据nums1和nums2两个数组长度总和是奇数还是偶数进行判断,是直接返回一个数值,还是两个数加和求平均再返回

    在这里插入图片描述

    class Solution {
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    
            int totalLength = nums1.length + nums2.length;
            int[] nums = new int[totalLength];
            int i = 0, j = 0;
            int index = 0;
            while (i < nums1.length && j < nums2.length) {
                if (nums1[i] < nums2[j]) {
                    nums[index] = nums1[i++];
                } else if (nums1[i] > nums2[j]) {
                    nums[index] = nums2[j++];
                } else {
                    nums[index] = nums1[i++];
                }
                if (index == totalLength / 2) {
                    //nums数组长度为偶数
                    if ((totalLength & 1) == 0) {
                        return (nums[index] + nums[index - 1]) / 2.0;
                    } else {
                        //nums数组长度是奇数
                        return 1.0 * nums[index];
                    }
                }
                index++;
            }
            if (i == nums1.length) {
                while (j <= nums2.length) {
                    nums[index] = nums2[j++];
                    if (index == totalLength / 2) {
                        //nums数组长度为偶数
                        if ((totalLength & 1) == 0) {
                            return (nums[index] + nums[index - 1]) / 2.0;
                        } else {
                            //nums数组长度是奇数
                            return 1.0 * nums[index];
                        }
                    }
                    index++;
                }
            }
            if (j == nums2.length) {
                while (i < nums1.length) {
                    nums[index] = nums1[i++];
                    if (index == totalLength / 2) {
                        //nums数组长度为偶数
                        if ((totalLength & 1) == 0) {
                            return (nums[index] + nums[index - 1]) / 2.0;
                        } else {
                            //nums数组长度是奇数
                            return 1.0 * nums[index];
                        }
                    }
                    index++;
                }
            }
            return 0.0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    就代码而言,感觉还是有一定的冗余,不精炼

    其他解法

    https://leetcode.cn/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/

    方案一 合并两个数组

    先将两个数组合并,两个有序数组的合并也是归并排序的一部分,然后根据是奇数、还是偶数,返回中位数

    和我的思路一样,不过代码看上去更简洁一些

    class Solution {
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int m = nums1.length;
            int n = nums2.length;
    
            //如果nums1数组的长度为0,只要返回nums2数组的中位数即可
            if (m == 0) {
    
                if ((n & 1) != 0) {
                    return nums2[n / 2];
                } else {
                    return (nums2[n / 2] + nums2[n / 2 - 1]) / 2.0;
                }
    
            } else if (n == 0) {
    
                if ((m & 1) != 0) {
                    return nums1[m / 2];
                } else {
                    return (nums1[m / 2] + nums1[m / 2 - 1]) / 2.0;
                }
            }
            int count = 0;
            int i = 0, j = 0;
            int[] nums = new int[m + n];
            while (count != (m + n)) {
                if (i == m) {
                    while (j != n) {
                        nums[count++] = nums2[j++];
                    }
                    break;
                }
                if (j == n) {
                    while (i != m) {
                        nums[count++] = nums1[i++];
                    }
                    break;
                }
                if (nums1[i] < nums2[j]) {
                    nums[count++] = nums1[i++];
                } else {
                    nums[count++] = nums2[j++];
                }
    
            }
            if ((count & 1) != 0) {
                return nums[count / 2];
            }
            return (nums[count / 2] + nums[count / 2 - 1]) / 2.0;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    时间复杂度

    遍历整个数组,O(m+n)

    空间复杂度

    开辟了一个数组,保存两个数组合并以后的结果O(m+n)

    方案二 不用合并数组,找到中位数即可

    如何将奇数和偶数的情况合并?

    用len表示合并后数组的长度

    • 如果是奇数,需要知道l第en/2+1个数字是什么,需要遍历len/2+1个数

      • 是奇数,需要最后一次的遍历结果
    • 如果是偶数,需要知道第len/2个数字和第len/2+1个数字是什么,也需要遍历len/2+1个数

      • 是偶数,需要最后一次和上一次的遍历结果

    用两个变量,pre和now,now保存当前循环的结果,在每次循环前将now的值赋值给pre。这样在最后一次循环的时候,pre将得到right的值,也就是上一次循环的结果,接下来,now更新为最后一次的结果
    在这里插入图片描述

    循环中,分别用aStart和bStart分别表示当前指向nums1数组和nums2数组的位置。

    如果aStart没有到最后,并且nums1中aStart位置上的数字小于nums2中bStart位置上的数字,那么,aStart可以往后移,也就是 aStart < m && nums1[aStart] < nums2[bStart]。

    上面的条件表达式,如果nums2数组已经遍历到头了,再取nums2[bStart]会数组越界,抛出异常,所以,要判断一下bStart是否大于等于nums2的数组长度,这样 || 后面的nums1[aStart] < nums2[bStart]就不会执行了,也就不会导致错误了。所以,增加为 aStart < m && (bStart >= n || nums1[aStart] < nums2[bStart])
    在这里插入图片描述

    class Solution {
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int m = nums1.length;
            int n = nums2.length;
            int len = m + n;
            int aStart = 0, bStart = 0;
            int pre = -1, now = -1;
            for (int i = 0; i <= len / 2; i++) {
                pre = now;
                if (aStart < m && (bStart >= n || nums1[aStart] < nums2[bStart])) {
                    now = nums1[aStart++];
                } else {
                    now = nums2[bStart++];
                }
            }
            if ((len & 1) != 1) {
                return (pre + now) / 2.0;
            }
            return now * 1.0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    时间复杂度

    遍历len/2+1次,len=m+n,所以,时间复杂度依旧是O(m+n)

    空间复杂度

    申请了常数个变量,所以是O(1)

  • 相关阅读:
    2023-9-11 拆分-Nim游戏
    短视频美食自媒体怎么做?5步教你快速上手
    【Django下载文件-Kml文件下载】
    【微服务部署】九、使用Docker Compose搭建高可用双机热备MySQL数据库
    AcWing基础部分Class2:高精度加减乘除、前缀和与差分
    使用vscode的ssh进行远程主机连接
    Python Django相关解答
    如何实现MQTT的Java代码
    C# 图解教程 第5版 —— 第1章 C# 和 .NET 框架
    租服务器太贵?流程太麻烦?教你如何免费解决
  • 原文地址:https://blog.csdn.net/guliguliguliguli/article/details/127457218