题目描述
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 示例:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
思路
这题主要考验我们怎么把俩个有序数组中的元素关联起来,知道他们在整体元素中的大小位置
1.暴力求解
将俩个数组合并为一个数组,利用sort()排序方法整理元素之间的大小,并且排序完成后的数组是知道他们元素位置和大小的
var findMedianSortedArrays = function(nums1, nums2) {
let result = nums1.concat(nums2);
result.sort((a,b)=>a-b);
let length = result.length;
if(length%2 === 0){
return (result[length/2]+result[length/2-1])/2;
}else{
return result[Math.floor(length/2)];
}
};
分析
- 将俩个数组合并为一个数组result
- 将result数组重新排序
- 利用result数组的长度得出其中位数所在位置
由于sort排序使用的是插入排序和快速排序 时间复杂度为O((m+n)log(m+n))
2. 双指针排序
还是将两个数组合并为一个数组,但是利用双指针的方法缩减时间复杂度
var findMedianSortedArrays = function(nums1, nums2) {
let reIndex = nums2.length-1;
for(let i = nums1.length-1; i>=0; i--){
while(nums2[reIndex]>=nums1[i] && reIndex > -1){
nums1.splice(i+1,0,...(nums2.splice(reIndex,1)));
reIndex--;
}
}
const result = nums2.concat(nums1);
const length = result.length;
return length%2 ? result[Math.floor(length/2)] : (result[length/2]+result[length/2-1])/2;
};
分析
-
- 外层循环控制nums1数组元素,内层循环控制nums2数组元素
-
- 将nums1数组与nums2数组的元素利用双指针法从末尾最大的数开始进行比较
-
- nums1[i]<nums2[reIndex]的话,将下标为reIndex的元素插入到nums1[i]的后面
-
- 当for循环结束时,只是将大于等于nums1[0]的nums2数组元素排好序
考虑特殊情况:
- 当for循环结束时,只是将大于等于nums1[0]的nums2数组元素排好序
-
当nums2数组其中部分元素可能小于nums1[0]
-
当其中一个数组为空时
因此在第四步加上一个步骤,在将将下标为reIndex的元素插入到nums1[i]的后面的同时,将这个元素从nums2中删除
为什么删除呢? nums2数组其中部分元素可能小于nums1中最小的元素,为了方便循环结束后,将剩下的nums2数组元素和已经排好序的nums1数组元素合并
合并操作的另一个原因: 防止其中一个数组是空数组
nums2.concat(nums1)
3. 二分查找
将时间复杂度缩减到O(log(m+n))
分析
这个我实在是能力有限 只能给贴一个官方视频了
总结
- 遇到每一道算法题,首先去思考它究竟需要怎么样的答案,不要偏题很重要。
- 理清楚思路后才开始敲代码,不要着急
- 一般暴力破解之后,都可以再优化,好好想想还是可以的
本文正在参与「掘金 2021 春招闯关活动」, 点击查看【 活动详情】