未能比较数组中的两个元素_算法3 寻找两个正序数组的中序数
问题描述:
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。要求设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000
提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
解题思路:
根据中位数的定义,当 m+n 是奇数时,中位数是两个有序数组中的第 (m+n)/2个元素,当 m+n 是偶数时,中位数是两个有序数组中的第 (m+n)/2个元素和第 (m+n)/2+1 个元素的平均值。因此,这道题可以转化成寻找两个有序数组中的第 k 小的数,其中 k 为 (m+n)/2 或 (m+n)/2+1。假设两个有序数组分别是A 和B。要找到第 k 个元素,我们可以比较A[k/2−1] 和 B[k/2−1],其中 / 表示整数除法。由于 A[k/2−1] 和 B[k/2−1] 的前面分别有 A[0..k/2−2] 和 B[0..k/2−2],即 k/2−1 个元素,对于 A[k/2−1] 和 B[k/2−1] 中的较小值,最多只会有(k/2−1)+(k/2−1)≤k−2 个元素比它小,那么它就不能是第 kk 小的数了。
因此我们可以归纳出三种情况:
如果 A[k/2−1]
如果 A[k/2−1]>B[k/2−1],则可以排除 B[0] 到 B[k/2−1]。
如果 A[k/2−1]=B[k/2−1],则可以归入第一种情况处理。
可以看到,比较 A[k/2−1] 和 B[k/2−1] 之后,可以排除 k/2 个不可能是第 k 小的数,查找范围缩小了一半。同时,我们将在排除后的新数组上继续进行二分查找,并且根据我们排除数的个数,减少 k 的值,这是因为我们排除的数都不大于第 k 小的数。
有以下三种情况需要特殊处理:
如果 A[k/2−1] 或者 B[k/2−1] 越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 k 的值,而不能直接将 k 减去 k/2。
如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 k 小的元素。
如果 k=1,我们只要返回两个数组首元素的最小值即可。
用一个例子说明上述算法。假设两个有序数组如下:
A:1349B:123456789
两个有序数组的长度分别是 4 和 9,长度之和是 13,中位数是两个有序数组中的第 7 个元素,因此需要找到第 k=7 个元素。
比较两个有序数组中下标为 k/2−1=2 的数,即 A[2] 和 B[2],如下面所示:
A: 1 3 4 9 ↑
B: 1 2 3 4 5 6 7 8 9 ↑
由于 A[2]>B[2],因此排除 B[0] 到 B[2],即数组B 的下标偏移(offset)变为 3,同时更新 k 的值:k=k−k/2=4。
下一步寻找,比较两个有序数组中下标为 k/2−1=1 的数,即 A[1] 和 B[4],如下面所示,其中方括号部分表示已经被排除的数。
A: 1 3 4 9 ↑
B: [1 2 3] 4 5 6 7 8 9 ↑
由于 A[1]
下一步寻找,比较两个有序数组中下标为 k/2−1=0 的数,即比较 A[2] 和 B[3],如下面所示,其中方括号部分表示已经被排除的数。
A: [1 3] 4 9 ↑
B: [1 2 3] 4 5 6 7 8 9 ↑
由于 A[2]=B[3],根据之前的规则,排除 A 中的元素,因此排除 A[2],即数组 A 的下标偏移变为 3,同时更新 k 的值:k=k−k/2=1。
由于 k 的值变成 1,因此比较两个有序数组中的未排除下标范围内的第一个数,其中较小的数即为第 k 个数,由于 A[3]>B[3],因此第 k 个数是 B[3]=4。
A: [1 3 4] 9 ↑
B: [1 2 3] 4 5 6 7 8 9 ↑
算法代码:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int length1 = nums1.length, length2 = nums2.length;
int totalLength = length1 + length2;
if(totalLength % 2 == 1){
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) {
return Math.min(nums1[index1], nums2[index2]);
}
// 正常情况
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);
index1 = newIndex1 + 1;
} else {
k -= (newIndex2 - index2 + 1);
index2 = newIndex2 + 1;
}
}
}
}
未能比较数组中的两个元素_算法3 寻找两个正序数组的中序数相关推荐
- js 数组添加n次相同元素_数组中两次出现相同元素之间的最大距离
js 数组添加n次相同元素 Prerequisite: Hashing data structure 先决条件: 哈希数据结构 Problem statement: 问题陈述: Find maximu ...
- c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 一个数组中,除两个元素其余都出现了两次,找出这两个元素
为什么80%的码农都做不了架构师?>>> 本文为转载,原文地址是:http://blog.csdn.net/morewindows/article/details/821400 ...
- 数组中的元素赋值给元素_漫画:寻找无序数组的第k大元素
本期封面作者:泰勒太乐 ----- 第二天 ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k=6,也就是要寻找第6大的元素,这个元素是哪一个呢? 显然,数组中第一大的元素是24,第 ...
- java删除有序数组中的重复元素_算法刷刷刷Leetcode第26题删除排序数组中的重复项...
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度.不要使用额外的数组空间,你必须在原地修改输入数组 并在使用 O(1) 额外空间的条件下完成.示例 ...
- ios 取出数组中前两个元素_看图学NumPy:掌握n维数组基础知识点,看这一篇就够了...
晓查 编译整理 量子位 报道 | 公众号 QbitAI NumPy是Python的最重要的扩展程序库之一,也是入门机器学习编程的必备工具.然而对初学者来说,NumPy的大量运算方法非常难记. 最近,国 ...
- c语言如何删除数组中的某一个元素_数据结构之线性表高效删除重复元素
刚刚学完数据结构之线性表中关于顺序表和单链表的知识,我们知道顺序表中存储数据的结构是一个数组,对于数组来说,在尾部插入.删除元素是比较高效的,但是如果在中间或者开头插入.删除元素,就会涉及数据的搬移, ...
- python取出矩阵中的某一元素_将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例...
在神经网络计算过程中,经常会遇到需要将矩阵中的某些元素取出并且单独进行计算的步骤(例如MLE,Attention等操作).那么在 tensorflow 的 Variable 类型中如何做到这一点呢? ...
- 航飞原始影像外方位元素_【技术】无人机倾斜摄影建模技术在虚拟现实中的应用...
(如有侵权,请联系删除) 摘 要 针对于虚拟现实平台中构建三维场景的费时费力问题,基于无人机倾斜摄影建模技术构建三维模型,利用 3DS Max 建模软件进行模型优化,并结合 Unity 3D 引擎构建 ...
最新文章
- 习题3-5 三角形判断 (15 分)
- 从pfx里面 解析出公私钥
- 集合详解(三)----Map的两种遍历方式
- PopupWindow的基本使用
- 打开另外一个页面_如何在PDF页面中插入图片?
- 从一个程序员的角度告诉你:12306有多牛逼?
- xp怎么删除计算机用户,谁了解xp系统如何删除工作组计算机
- Oracle+ogg-00664,OGG采用NET8方式读取ASM中日志报OGG-00664(ORA-12162),配置如下:
- Mac 右键展示Copy path
- 在服务器上如何打开mdf文件,在没sql server数据库状况下怎么打开.mdf文件
- 一款基于java开发的开源监控平台
- PMP 敏捷管理相关知识点
- qpython androidhelper_QPython Androidhelper Api文档
- HP-UX 基本命令学习
- input[type=file]如何屏蔽“未选择任何文件”
- 【机器学习】一文读懂正则化与LASSO回归,Ridge回归
- 嵌入式开发五:未来之星机器人语音控制及视频开发(颜色追踪)(运动追踪)
- 用上这门黑科技,运维从此不背锅!
- KPI考核系统实战之一:环境搭建
- Unity CPU优化卡顿
热门文章
- 在后台查看product的change history
- 用SAP BSP应用实现图片灰度效果
- 单步调试理解webpack里通过require加载nodejs原生模块实现原理
- Kibana功能一览
- CRM订单状态的Open, In process和Completed这些条目是从哪里来的
- java ibatis 获取执行的sql_小程序官宣+JAVA 三大框架基础面试题
- 河北省单招计算机类考试考英语吗,2019年河北省高职单招考试十类 和对口电子电工类、计算机类联考 专业基础考试(英语)考试大纲.doc...
- jeecg-boot自动生成代码_无代码实现销售系统自动判定并生成订单功能
- 将image存入mysql数据库_有谁知道如何把一图片存放到mysql数据库中
- 格雷编码Python解法