前言
本文介绍了 LeetCode 第 4 题 , “Median of Two Sorted Arrays”, 也就是 “寻找两个有序数组的中位数” 的问题.
本文使用 C# 语言完成题目,介绍了多种方法供大家参考。
题目
English
LeetCode 4. Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
中文
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)) 的 时间复杂度要求。根据 LeetCode 题解中 windliang 提供的方法“第k小数”方法,时间复杂度可以达到题目要求;根据 LeetCode 官方题解中提供的方法,时间复杂度可以达到 O( log( min(m,n)) ) ,比题目要求的时间复杂度还要小。下面我们依次来介绍这几种方法。
方法一 : 合并List根据长度找中位数
new 一个 List , 并将 nums1 和 nums2 都添加到list 中,然后进行排序。对于排序后的 list, 根据长度计算出中位数的index,进而计算出最终结果。
假设合并后的list长度为13,则从小到大第7个数字为中位数,resultIndex=6;
假设合并后的list长度为14,则从小到大第7,8个数字的平均值为中位数,index 分别为 6,7,此时resultIndex =7,resultIndex-1 =6 , 结果为 ( list[resultIndex-1] + list[resultIndex] ) / 2.0 ;
public double FindMedianSortedArrays(int[] nums1, int[] nums2)
{
int m = nums1.Length;
int n = nums2.Length;
int len = m + n;
var resultIndex = len / 2;
List<int> list = new List<int>(nums1);
list.AddRange(nums2);
list.Sort();
if (len % 2 == 0)
{
return (list[resultIndex - 1] + list[resultIndex]) / 2.0;
}
else
{
return list[resultIndex];
}
}
执行结果
执行结果 通过,执行用时 156ms,内存消耗 27.2MB .
复杂度分析
时间复杂度:O( (m+n)(1+log(m+n) ))
将长度为m,n的两个数组添加到list,复杂度分别为常数级的m和n ;list.Sort()的复杂度根据官方文档可得为 (m+n)log(m+n),所以该方法时间复杂度为 O( m+n+(m+n)log(m+n) ) = O( (m+n)(1+log(m+n) ))
空间复杂度:O(m+n)
使用list的长度为m+n.
方法二 : 归并排序后根据长度找中位数
方法一使用了list.Sort() 方法,可以对list进行排序,但是,若题目给出的nums1 和 nums2 是无序数组,使用 list.Sort() 才算是 物有所用。 本题中 nums1 和 nums2 是有序数组,所以使用 list.Sort() 有写 杀鸡用宰牛刀的感觉,换句话说,这里面存在着效率的浪费。我们可以利用 【nums1 和 nums2 是有序数组】 这个条件,来精简我们的排序。
public double FindMedianSortedArrays(int[] nums1, int[] nums2)
{
// nums1 与 nums2 有序添加到list中
List<int> list = new List<int>();
int i = 0, j = 0;
int m = nums1.Length;
int n = nums2.Length;
int len = m + n;
var resultIndex = len / 2;
while (i < m && j < n)
{
if (nums1[i] < nums2[j])
list.Add(nums1

本文详细介绍了如何使用C#解决LeetCode第4题,寻找两个有序数组的中位数。讨论了多种方法,包括合并数组找中位数、归并排序后找中位数、优化版不合并数组、第k小数方法以及直接根据中位数定义解题,其中第k小数方法实现了O(log(m+n))的时间复杂度。
最低0.47元/天 解锁文章
3万+

被折叠的 条评论
为什么被折叠?



