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
思考:
看了Grandyang的博客,慢慢想明白才写的!真的是很细心耐心的博主!
限制了时间复杂度为O(log (m+n)),想到了应该使用二分查找法来求解。
寻找数组的中位数的小技巧:假设数组的长度是m,找第(m+1)/2位和第(m+2)/2位的元素,两者的平均数即为数组的中位数。
我们可以在两个数组之间使用二分查找。分别去查找每个数组的(m+n+1)/2的元素和(m+n+2)/2的元素求平均数。
首先:定义一个函数来在两个有序数组中找到第K个元素(这道题可以出成:两个有序数组找第N大)
有两个边缘情况要注意:
1、当数组的起始位置已经大于等于数组的长度(这时只用去寻找另一个数组即可),此时表明这个数组中所有元素已经被排除了,所以直接去寻找另一个数组起始位置:j + k /2 -1的元素。
2、当K == 1时,表示要查找当前数组的首元素,举个例子如下图:
算法思路:
分别在nums1和nums2中查找第K/2个元素,数组长度是不定的,所以要确定当前的数组有没有k/2个元素,如果存在就取作midval值,否则就赋值上一个整型最大值INT_MAX。如果某个数组没有第K/2个数字,那么我们就淘汰另一个数组的前K/2个数字即可。若找到的midVal1 大于 midVal2,说明该去查找num1的下半区间[i +k/2 -1 +1,end] (i+k/2 -1 :mid 另外一半区间应该是起始mid +1 ),有序数组的中位数,左边的都比它小,右边的都比它大。
重点理解:“如果某个数组没有第K/2个数字,那么我们就淘汰另一个数组的前K/2个数字即可。”
一开始没理解后来主动问了博主:Grandyang。举例子:假设nums1 ={3},nums2={2,4,5,6,7},K=4,我们要在两个数组中找第四个的元素,分别在nums1和nums2中找第2个的元素,现在nums1只有一个数字,所以不存在第二大的数字,而nums2前两个数字可以直接跳过。
因为要求整个两个数组中第4个的元素,如果num1中数字大于num2第k/2位,那么合并之后也是在num2第k/2位之后,而num2的前k/2位是没用的,直接跳过;如果num1中数字是小于num2第k/2位置,但是元素个数是小于k/2,即使合并,这两部分元素个数也只小于k个,所以也不可能在num2的k/2部分,所以第4个的元素肯定不会出现在一个排序数组nums2的前两位,所以可以直接跳过。
/*查找两个数组中排列第K个数*/
int findKthNumber(vector<int>& nums1,int i ,vector<int>& nums2,int j,int k){if(i >= nums1.size()) return nums2[j+k-1];if(j >= nums2.size()) return nums1[i+k-1];//if(k ==1) return (double(nums1[i] + nums2[j]));wrongif(k == 1) return min(nums1[i],nums2[j]);//查找有没有k/2个元素int midVal1 = (i+k/2-1 < nums1.size())?nums1[i+k/2-1]:INT_MAX;int midVal2 = (j+k/2-1 < nums2.size())?nums2[j+k/2-1]:INT_MAX;if(midVal1 < midVal2)/*二分查找,丢弃前半部分包括正中间的数,因为二分查找正是利用中间的数来进行比较*/return findKthNumber(nums1,i+k/2,nums2,j,k-k/2);elsereturn findKthNumber(nums1,i,nums2,j+k/2,k-k/2);
}
还有一个地方值得注意:二分查找的时候,是利用中间数位的值进行比较,所以下一次递归的起始位置就应该从mid+1开始,或者截止位置到mid-1。
整体代码:
/*分清 起始位置 和 第几个元素 */
int findKthNumber(vector<int>& nums1,int i ,vector<int>& nums2,int j,int k){if(i >= nums1.size()) return nums2[j+k-1];if(j >= nums2.size()) return nums1[i+k-1];//if(k ==1) return (double(nums1[i] + nums2[j]));wrongif(k == 1) return min(nums1[i],nums2[j]);//查找有没有k/2个元素的位置 i + k/2 -1 int midVal1 = (i+k/2-1 < nums1.size())?nums1[i+k/2-1]:INT_MAX;int midVal2 = (j+k/2-1 < nums2.size())?nums2[j+k/2-1]:INT_MAX;if(midVal1 < midVal2)return findKthNumber(nums1,i+k/2,nums2,j,k-k/2);elsereturn findKthNumber(nums1,i,nums2,j+k/2,k-k/2);
}
class Solution {
public:double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {int m = nums1.size(),n = nums2.size();int left = (m+n+1)/2,right = (m+n+2)/2;return (findKthNumber(nums1,0,nums2,0,left)+findKthNumber(nums1,0,nums2,0,right))/2.0;}
};
4. 寻找两个有序数组的中位数(☆☆☆)相关推荐
- 算法--------------------寻找两个有序数组的中位数
题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)).你可以假设 nums1 和 num ...
- 两个有序数组的中位数 python_Python寻找两个有序数组的中位数实例详解
Python寻找两个有序数组的中位数 审题: 1.找出意味着这是一个查找算法题 2.算法复杂度log级别,就是提示你是二分查找 3.二分查找实现一般为递归 (1)递归包括递归体 (2)终止条件 思路: ...
- LeetCode4. 寻找两个有序数组的中位数
4. 寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假 ...
- 20191016:(leetcode习题)寻找两个有序数组的中位数
寻找两个有序数组的中位数 题目 大致思路 代码实现 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log( ...
- (JS)寻找两个有序数组的中位数
寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 n ...
- Python寻找两个有序数组的中位数
Python寻找两个有序数组的中位数 审题: 找出意味着这是一个查找算法题 算法复杂度log级别,就是提示你是二分查找 二分查找实现一般为递归 (1)递归包括递归体 (2)终止条件 思路: 定理: 有 ...
- 力扣寻找两个有序数组的中位数
寻找两个有序数组的中位数 要求 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假 ...
- LeetCode(Python实现)—寻找两个有序数组的中位数
4.寻找两个有序数组的中位数 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). ...
- 分享一道力扣困难题~寻找两个有序数组的中位数(Java)
目录 解题思路1 具体代码 解题思路2 具体代码 题目描述:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 .算法的时间复杂 ...
- 【LeetCode】寻找两个有序数组的中位数【性质分析+二分】
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...
最新文章
- 2345浏览器网址_2345网址导航回应“浏览器主页劫持”丨开发者日报
- 【10】青龙面板之JD ck 获取的1种办法
- bootstrap 起步
- 微信小程序 自定义tabBar
- javascript调用一个函数(对象),new和直接调用的区别
- 0x01第一个汇编程序
- LVS学习笔记 5高可用集群原理
- 2020年,程序员如何优雅地赚更多的钱?
- CAD图纸打印出来后很多CAD文字消失了怎么办?
- Android屏幕截图实现方式 系统截屏源码分析和三指截屏
- 【马红“名师+”研修共同体成员风采】
- 超详细的《使用腾讯云移动直播开发连麦》
- 2020年中国SCADA行业产值、市场规模及竞争格局分析[图]
- Connection could not be established with host smtp.163.com 阿星小栈
- 使用C++实现FC红白机模拟器 Cartridge 与 Mapper(实现篇)
- FPGA实现JPEG-LS图像压缩,有损无损可配置,提供工程源码和技术支持
- MKR基于知识图谱的推荐算法
- 博途PLC的模糊PID(Matlab “fuzzy“工具箱使用介绍)
- Windows 11 蓝屏 Stop code - SYSTEM SERVICE EXCEPTION What failed - igdkmd64.sys
- git 同步服务器上最新的代码