问题描述:

给定两个大小为 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 寻找两个正序数组的中序数相关推荐

  1. js 数组添加n次相同元素_数组中两次出现相同元素之间的最大距离

    js 数组添加n次相同元素 Prerequisite: Hashing data structure 先决条件: 哈希数据结构 Problem statement: 问题陈述: Find maximu ...

  2. c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  3. 一个数组中,除两个元素其余都出现了两次,找出这两个元素

    为什么80%的码农都做不了架构师?>>>    本文为转载,原文地址是:http://blog.csdn.net/morewindows/article/details/821400 ...

  4. 数组中的元素赋值给元素_漫画:寻找无序数组的第k大元素

    本期封面作者:泰勒太乐 -----  第二天  ----- 题目是什么意思呢?比如给定的无序数组如下: 如果 k=6,也就是要寻找第6大的元素,这个元素是哪一个呢? 显然,数组中第一大的元素是24,第 ...

  5. java删除有序数组中的重复元素_算法刷刷刷Leetcode第26题删除排序数组中的重复项...

    给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度.不要使用额外的数组空间,你必须在原地修改输入数组 并在使用 O(1) 额外空间的条件下完成.示例 ...

  6. ios 取出数组中前两个元素_看图学NumPy:掌握n维数组基础知识点,看这一篇就够了...

    晓查 编译整理 量子位 报道 | 公众号 QbitAI NumPy是Python的最重要的扩展程序库之一,也是入门机器学习编程的必备工具.然而对初学者来说,NumPy的大量运算方法非常难记. 最近,国 ...

  7. c语言如何删除数组中的某一个元素_数据结构之线性表高效删除重复元素

    刚刚学完数据结构之线性表中关于顺序表和单链表的知识,我们知道顺序表中存储数据的结构是一个数组,对于数组来说,在尾部插入.删除元素是比较高效的,但是如果在中间或者开头插入.删除元素,就会涉及数据的搬移, ...

  8. python取出矩阵中的某一元素_将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例...

    在神经网络计算过程中,经常会遇到需要将矩阵中的某些元素取出并且单独进行计算的步骤(例如MLE,Attention等操作).那么在 tensorflow 的 Variable 类型中如何做到这一点呢? ...

  9. 航飞原始影像外方位元素_【技术】无人机倾斜摄影建模技术在虚拟现实中的应用...

    (如有侵权,请联系删除) 摘 要 针对于虚拟现实平台中构建三维场景的费时费力问题,基于无人机倾斜摄影建模技术构建三维模型,利用 3DS Max 建模软件进行模型优化,并结合 Unity 3D 引擎构建 ...

最新文章

  1. 习题3-5 三角形判断 (15 分)
  2. 从pfx里面 解析出公私钥
  3. 集合详解(三)----Map的两种遍历方式
  4. PopupWindow的基本使用
  5. 打开另外一个页面_如何在PDF页面中插入图片?
  6. 从一个程序员的角度告诉你:12306有多牛逼?
  7. xp怎么删除计算机用户,谁了解xp系统如何删除工作组计算机
  8. Oracle+ogg-00664,OGG采用NET8方式读取ASM中日志报OGG-00664(ORA-12162),配置如下:
  9. Mac 右键展示Copy path
  10. 在服务器上如何打开mdf文件,在没sql server数据库状况下怎么打开.mdf文件
  11. 一款基于java开发的开源监控平台
  12. PMP 敏捷管理相关知识点
  13. qpython androidhelper_QPython Androidhelper Api文档
  14. HP-UX 基本命令学习
  15. input[type=file]如何屏蔽“未选择任何文件”
  16. 【机器学习】一文读懂正则化与LASSO回归,Ridge回归
  17. 嵌入式开发五:未来之星机器人语音控制及视频开发(颜色追踪)(运动追踪)
  18. 用上这门黑科技,运维从此不背锅!
  19. KPI考核系统实战之一:环境搭建
  20. Unity CPU优化卡顿

热门文章

  1. 在后台查看product的change history
  2. 用SAP BSP应用实现图片灰度效果
  3. 单步调试理解webpack里通过require加载nodejs原生模块实现原理
  4. Kibana功能一览
  5. CRM订单状态的Open, In process和Completed这些条目是从哪里来的
  6. java ibatis 获取执行的sql_小程序官宣+JAVA 三大框架基础面试题
  7. 河北省单招计算机类考试考英语吗,2019年河北省高职单招考试十类 和对口电子电工类、计算机类联考 专业基础考试(英语)考试大纲.doc...
  8. jeecg-boot自动生成代码_无代码实现销售系统自动判定并生成订单功能
  9. 将image存入mysql数据库_有谁知道如何把一图片存放到mysql数据库中
  10. 格雷编码Python解法