当前位置:网站首页>【Hot100】4. 寻找两个正序数组的中位数
【Hot100】4. 寻找两个正序数组的中位数
2022-06-28 15:51:00 【王六六的IT日常】
困难题
参考:
有三种解法:
①
// 第k小数
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int length1 = nums1.length, length2 = nums2.length;
int totalLength = length1 + length2;
if (totalLength % 2 == 1) {
// 可以将两种情况合并,奇数会求两次同样的k
int midIndex = totalLength / 2;
double median = getKthElement(nums1, nums2, midIndex + 1);
return median;
} else {
int midIndex1 = totalLength / 2 - 1, midIndex2 = totalLength / 2;
double median = (getKthElement(nums1, nums2, midIndex1 + 1) + getKthElement(nums1, nums2, midIndex2 + 1)) / 2.0;
return median;
}
}
public int getKthElement(int[] nums1, int[] nums2, int k) {
/* 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较 * 这里的 "/" 表示整除 * nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个 * nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个 * 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个 * 这样 pivot 本身最大也只能是第k-1小的元素 * 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组 * 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组 * 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数 */
int length1 = nums1.length, length2 = nums2.length;
int index1 = 0, index2 = 0;
int kthElement = 0;
while (true) {
// 特殊情况
if (index1 == length1) {
// 第二种特殊情况,一个数组为空
return nums2[index2 + k - 1];
}
if (index2 == length2) {
// 第二种特殊情况,一个数组为空
return nums1[index1 + k - 1];
}
if (k == 1) {
// 第三种特殊情况,k=1
return Math.min(nums1[index1], nums2[index2]);
}
// 正常情况,index1,index2作为起始点,newindex1,newindex2作为比较点 在不停的更新
int half = k / 2;
int newIndex1 = Math.min(index1 + half, length1) - 1; //第一种特殊情况,发生越界,记录需要比较的位置
int newIndex2 = Math.min(index2 + half, length2) - 1; //第一种特殊情况,发生越界,记录需要比较的位置
int pivot1 = nums1[newIndex1], pivot2 = nums2[newIndex2]; //获取两个需要比较的数
if (pivot1 <= pivot2) {
// <=将两种情况合并
k -= (newIndex1 - index1 + 1); //两者相减后+1,这才是真正减去的长度
index1 = newIndex1 + 1; //连同比较位置也一同删去了,所以新的开始是 比较位置 的后一位
} else {
k -= (newIndex2 - index2 + 1);
index2 = newIndex2 + 1;
}
}
}
}
②
// 常规思想
class Solution {
public double findMedianSortedArrays(int[] A, int[] B) {
int m = A.length;
int n = B.length;
int len = m + n;
int left = -1, right = -1;
int aStart = 0, bStart = 0;
for (int i = 0; i <= len / 2; i++) {
left = right; // 每次循环前将 right 的值赋给 left
// A移动的条件: B遍历到最后 或 当前A<B,满足一个即可
if (aStart < m && (bStart >= n || A[aStart] < B[bStart])) {
right = A[aStart++];
} else {
right = B[bStart++];
}
}
if ((len & 1) == 0) // 与1交,判断奇偶数,更快速
return (left + right) / 2.0;
else
return right;
}
}
③
// 划分数组
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return findMedianSortedArrays(nums2, nums1);
}
int m = nums1.length;
int n = nums2.length;
int left = 0, right = m;
// median1:前一部分的最大值
// median2:后一部分的最小值
int median1 = 0, median2 = 0;
while (left <= right) {
// 一直循环找到一个最大的i满足A[i-1]≤B[j]
// 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
// 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]
int i = (left + right) / 2; //二分法,i从区间中间开始
int j = (m + n + 1) / 2 - i;//+1的操作将总数为奇数和偶数合并为一种情况
//nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]
//当一个数组不出现在前一部分时,对应的值为负无穷,就不会对前一部分的最大值产生影响
int nums_im1 = (i == 0 ? Integer.MIN_VALUE : nums1[i - 1]);
//当一个数组不出现在后一部分时,对应的值为正无穷,就不会对后一部分的最小值产生影响
int nums_i = (i == m ? Integer.MAX_VALUE : nums1[i]);
int nums_jm1 = (j == 0 ? Integer.MIN_VALUE : nums2[j - 1]);
int nums_j = (j == n ? Integer.MAX_VALUE : nums2[j]);
if (nums_im1 <= nums_j) {
median1 = Math.max(nums_im1, nums_jm1);
median2 = Math.min(nums_i, nums_j);
left = i + 1;
}
else {
right = i - 1;
}
}
return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;
}
}
边栏推荐
- 【MySQL】表连接为什么比子查询快
- Technical secrets of ByteDance data platform: implementation and optimization of complex query based on Clickhouse
- 请问下大家有遇到过这种设置的主健和数据库一致的错误吗?
- GAIN的代码实现(4)——基于GAN的Spam数据集缺失数据填补(序)【改进版】
- ID卡复制教程(使用T5577卡复制4100卡)
- 【MySQL】官网文档学习之查询语句sql注意事项
- NFT质押LP流动性挖矿系统开发详情
- A 24-year-old bald programmer teaches you how to continuously integrate and deliver microservice delivery. You can't learn how to cut me off
- 机器学习之深度学习卷积神经网络,实现基于CNN网络的手写字体识别
- Visual Studio 2010 compilation qt5.6.3
猜你喜欢

一台服务器最大并发 tcp 连接数多少?65535?

【Proteus仿真】L297驱动步进电机

10年测试经验,在35岁的生理年龄面前,一文不值

软件测试员的悲哀竟是...自己的技术能力不能满足大厂要求?

【初学者必看】vlc实现的rtsp服务器及转储H264文件

Talking about open source - Linus and Jim talk about open source in China
![[Spock] process non ASCII characters in an identifier](/img/ab/d2cd6802d1e2af009da077ae82bdf8.png)
[Spock] process non ASCII characters in an identifier

关注35岁的坎:畏惧是因为你没有匹配这个年纪该有的能力

Knowing these commands allows you to master shell's own tools

今天睡眠质量记录80分
随机推荐
抖音实战~我关注的博主列表、关注、取关
Visual Studio 2019软件安装包和安装教程
使用openpyxl操作Excel
tablestore中可以使用sql查询可以查出表中所有的数据吗?
同创伟业合伙人童子平:“元宇宙”究竟该投什么
[Spock] process non ASCII characters in an identifier
PostgreSQL enables grouping statistics by year, month, day, week, hour, minute and second
全球陆续拥抱Web3.0,多国已明确开始抢占先机
Jenkins的安装及使用
Flutter简单实现多语言国际化
10 years of testing experience, worthless in the face of the physiological age of 35
[MySQL] official website document learning query statement SQL precautions
NFT质押LP流动性挖矿系统开发详情
Operating excel with openpyxl
The world has embraced Web3.0 one after another, and many countries have clearly begun to seize the initiative
Expand Disk C (allocate the memory of disk d to Disk C)
机器学习之卷积神经网络Lenet5训练模型
关注35岁的坎:畏惧是因为你没有匹配这个年纪该有的能力
Naacl 2022 | distillation of machinetranslation SOTA model
leetcode:22. 括号生成