leetcode:4.寻找两个有序数组的中位数

简介: 题目比较好理解,如果只看最后结果的话,很容易想到把两个数组合并,并且排序后就可以轻松的找到中位数,但这样不符合题目的意思

题目描述:


给定两个大小为 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


题目难度:困难


分析:


题目比较好理解,如果只看最后结果的话,很容易想到把两个数组合并,并且排序后就可以轻松的找到中位数,但这样不符合题目的意思,因为要求的时间复杂度为O(log(m+n))。这样一来不管你怎么合并排序都不可能达到题目要求,最好的也是O(nlogn)这个级别。代码如下:


class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
      // 定义一个大的数组用来存放两个小数组
        int[] nums3 = new int[nums1.length + nums2.length];
        // 分别把两个数组放在nums3里面
        for (int i = 0; i < nums1.length; i++) {
            nums3[i] = nums1[i];
        }
        for (int i = nums1.length, j = 0; i < nums3.length; i++, j++) {
            nums3[i] = nums2[j];
        }
        // 对数组排序
        Arrays.sort(nums3);
        // 对有序数组来说,只要根据数组的长度就可以轻松找到中位数。
        return nums3.length % 2 == 0 ?
                (nums3[nums3.length / 2 - 1] + nums3[nums3.length / 2]) / 2.0 :                                     nums3[nums3.length / 2];
    }
}


小结:


时间复杂度为O(nlogn),这里为了省事,直接调用了API,虽不合法要求,但是结果是对的,执行速度较慢。


扩展:


根据题目的意思,是两个已经排好序的数组了,如果要合并的话,其实可以用二路归并排序,虽然时间复杂度也是O(nlogn),但是前面的步骤都省略了,只需要最后的一个合并步骤即可,所以速度会快跟多,目前排名第一的代码如下(搬运):


class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int nums2length = nums2.length;
    // 定义一个大的数组用来存放两个小数组
    int[] r = new int[nums1.length + nums2length];
    int index = 0;
    int j = 0;
    /* 双层for循环,只要内层的元素小于外层的元素就把内层的元素放入数组中,
     这样一来肯定会把nums2中所有小的元素放在最前面,直到找到一个比nums1中的元素
     更大的,再把他放入即可,重复操作,即可以nums1中的元素和nums2中部分元素排序放好。
     */
    for (int num : nums1) {
      while (j < nums2length && num > nums2[j]) {
        r[index] = nums2[j];
        j++;
        index++;
      }
      r[index] = num;
      index++;
    }
    // 这一步是把nums2中剩下的元素依次放入,因为前一个步骤中可能会因为
    //nums2.length > nums1.length。导致nums2会漏掉后面的部分元素。
    for (; j < nums2length; j++) {
      r[index] = nums2[j];
      index++;
    }
    // 最后一步就是在排好序的数组中找到中位数即可。
    int mi = r.length / 2;
    return r.length % 2 == 1 ? r[mi] : (r[mi - 1] + r[mi]) / 2.0;
  }
}


小结:


此方法比较好理解,速度也快(不愧是排名第一的),巧妙的把两个排好序的数组放入一个大数组中,然后即可求出中位数。


总结:


简单的算法和想法不一定是慢的,有时候往往有奇效。

目录
相关文章
|
6月前
|
Go 索引 Perl
【LeetCode 热题100】【二叉树构造题精讲:前序 + 中序建树 & 有序数组构造 BST】(详细解析)(Go语言版)
本文详细解析了二叉树构造的两类经典问题:通过前序与中序遍历重建二叉树(LeetCode 105),以及将有序数组转化为平衡二叉搜索树(BST,LeetCode 108)。文章从核心思路、递归解法到实现细节逐一拆解,强调通过索引控制子树范围以优化性能,并对比两题的不同构造逻辑。最后总结通用构造套路,提供进阶思考方向,帮助彻底掌握二叉树构造类题目。
284 9
|
12月前
leetCode(删除有序数组中的重复项)
如何在不使用额外空间的情况下,通过双指针法原地删除有序数组中的重复项。
95 2
|
存储 Java API
LeetCode------合并两个有序数组(4)【数组】
这篇文章介绍了LeetCode上的"合并两个有序数组"问题,并提供了三种解法:第一种是使用Java的Arrays.sort()方法直接对合并后的数组进行排序;第二种是使用辅助数组和双指针技术进行合并;第三种则是从后向前的双指针方法,避免了使用额外的辅助数组。
LeetCode------合并两个有序数组(4)【数组】
LeetCode第26题删除有序数组中的重复项
这篇文章介绍了LeetCode第26题"删除有序数组中的重复项"的解题方法,通过使用双指针技巧,高效地去除数组中的相邻重复元素。
LeetCode第26题删除有序数组中的重复项
LeetCode第80题删除有序数组中的重复项 II
文章介绍了LeetCode第80题"删除有序数组中的重复项 II"的解法,利用双指针技术在O(1)空间复杂度内原地删除重复元素,并总结了双指针技术在处理有序数组问题中的应用。
LeetCode第80题删除有序数组中的重复项 II
|
12月前
【LeetCode 48】108.将有序数组转换为二叉搜索树
【LeetCode 48】108.将有序数组转换为二叉搜索树
104 0
LeetCode第88题合并两个有序数组
文章分享了LeetCode第88题"合并两个有序数组"的解法,通过从后向前的合并策略避免了数组元素的前移,使用三个指针高效地完成了合并过程。
|
Python
【Leetcode刷题Python】108. 将有序数组转换为二叉搜索树
LeetCode上108号问题"将有序数组转换为二叉搜索树"的Python实现,通过递归选取数组中间值作为根节点,构建高度平衡的二叉搜索树。
93 2
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
146 0
|
Python
【Leetcode刷题Python】26. 删除有序数组中的重复项
本文提供了一种使用快慢指针法在原地删除升序数组中重复元素的Python实现,返回删除后数组的新长度,同时保持元素的相对顺序。
104 0

热门文章

最新文章