两个有序数组的上中位数和第K小数问题
哈,再介绍个操蛋的问题。当然,网上有很多解答,但是能让你完全看懂的不多,即便它的结果是正确的,可是解释上也是有问题的。
所以,为了以示正听,我也做了分析和demo,只要你愿意学习,你就一定能学会,并且不会有疑惑了。
可以侧面反映我的分析和算法都是逻辑严格,阐述清晰了。
————————————————————————————————————————————
原问题出于leetcode
Leetcode当然又是来源于实践了:对于两个有序的数组(升序),设A[],长度m, B[],长度为n, 如何找到第K小的数(此处根据中文语境做了处理,大多数资料都是照搬英文字面含义称为第K大数),当K为(m+n)/2时,结果就是上中位数。
我想在实际的应用领域中,估计会有这种需求出现,用最简单的两有序数组合并,然后自然得出需要的结果,时间复杂度接近于O(m+n)。而这个问题是存在O(log(m+n))时间复杂度的解决方案的,对于log级别的算法一定是二分查找,这里二分的类别就应该是有序的区间端。
解:第K小数
A,B两个数组,A的长度小于B,分别为m, n。如果m==0,则B[k-1]即为所求。1==K时,A[0]与B[0]中较小的那个即为所求。其它情况分析如下,取A数组的前num1个元素的子数组A1,再取B数组的前K-num1个元素的子数组B。我们设A1长度l1, B!长度l2。如果,B[l2-1]==A[l1-1],A1和B1升序合并后应该改是…C[K-2],C[K-1],其中C[k-2]==C[k-1],值是A[l1-1]于B[l2-1]的其中之一,由于l1+l2==K,故而,我们找到了两个数组的第K小数就是C[K-1],也即是A[l1-1]或者B[l2-1];还剩下两种情况待分析,我们分别列出:
① A[l1-1]>B[l2-1]
此时,B可以分成两个子数组B[0…l2-1], B[l2...n-1]。这时候有一个关键问题需要理解,那就是B[0…l2-1]一定在第K小数序列之内, 因为如果A[l1-1]就是第K小数的话,B[0…l2-1]的l2个元素一定在它之前,所以B[0…l2-1]中不存在第K小数,第K小数只能在B[l2…n-1]中,或者在A[0…l1-1]中出现,因为我们已经有l2个K小数之前的元素,只要在上两个数组中取出l1的小数,就可知道l2+l1=K, 也就是第A,B数组的第K小数求出。当然,A[0…l1-1],B]l2…n-1]中的l1小数的求解也是一样的过程,这样就可以递归算法实现了。
② A[l1-1]<B[l2-1]
与上一种情况是互补的,所以很容易分析出。
算法
//array2k.c
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>
int find2k(int array1[], int len1, int array2[], int len2, int k)
{
if (k<0)
{
fprintf(stderr, "k value is no ligal\n");
return -1;
}
// make sure len1<=len2
if (len1>len2)
{
return find2k(array2, len2, array1, len1, k);
}
// return condition
if (0==len1)
{
return array2[k-1];
}
if (1==k)
{
return array1[0]>=array2[0]?array2[0]:array1[0];
}
// num1+num2==k
int num1 = len1>=k/2?k/2:len1;
int num2 = k-num1;
if (array1[num1-1]==array2[num2-1])
{
return array1[num1-1];
}
else if (array1[num1-1]>array2[num2-1])
{
return find2k(array1, num1, &array2[num2], len2-num2, k-num2);
}
else
{
return find2k(&array1[num1], len1-num1, array2, num2, k-num1);
}
}
//test.c
#include "array2k.h"
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>
void main()
{
int array1[11] = {10,21,22,35,47,56,67};
int array2[11] = {33,44,55,63,72,83};
// 7==k
int ret = find2k(array1, 7, array2, 6, 7);
printf("7==k, %d\n", ret);
//k==(7+6)/2, mid number
ret = find2k(array1, 7, array2, 6, 6);
printf("6==k(mid number), %d\n", ret);
}
//result:
# ./test
7==k, 47
6==k(mid number), 44
Finally:
这两个问题是普遍和特性问题,应该是上中位问题是是第K小数问题的特例,而不是网上有些人说的用特列之上中位来求第K小数,哪里的分析我也看了,云里雾里得,因为它的前提就错了。
有序数组的最低时间复杂度的排序和查找问题,应该是实际工程中比较重要的算法需求,所以,这个问题还是请重视一下。
两个有序数组的上中位数和第K小数问题的更多相关文章
- 【分步详解】两个有序数组中的中位数和Top K问题
(这也是一道leetcode的经典题目:<LeetCode>解题笔记:004. Median of Two Sorted Arrays[H] 问题介绍 这是个超级超级经典的分治算法!!这个 ...
- 两个有序数组中的中位数以及求第k个最小数的值
解法参考 <[分步详解]两个有序数组中的中位数和Top K问题> https://blog.csdn.net/hk2291976/article/details/51107778 里面求中 ...
- 每天一道算法题目(18)——取等长有序数组的上中位数和不等长有序数组的第k小的数
1.取上中位数 题目: 给定两个有序数组arr1和arr2,两个数组长度都为N,求两个数组中所有数的上中位数.要求:时间复杂度O(logN). 例如: arr1 = {1, ...
- [LeetCode] Median of Two Sorted Arrays 两个有序数组的中位数
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...
- 两个有序数组的中位数(第k大的数)
问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 感觉这种题目挺难的,尤其是将算法完全写对.因为当初自己微软面试的时候遇到了,但是没有想出来思路. ...
- 求两个有序数组的中位数或者第k小元素
问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...
- Leetcode题库——4.寻找两个有序数组的中位数
@author: ZZQ @software: PyCharm @file: findMedianSortedArrays.py @time: 2018/10/10 19:24 说明:给定两个大小为 ...
- LeetCode Golang 4. 寻找两个有序数组的中位数
4. 寻找两个有序数组的中位数 很明显我偷了懒, 没有给出正确的算法,因为官方的解法需要时间仔细看一下... func findMedianSortedArrays(nums1 []int, nums ...
- 寻找两个有序数组的中位数 C++实现leetcode系列(四)
给定两个大小为 m 和 n 的有序数组 nums1和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 不 ...
随机推荐
- Spark性能优化指南-高级篇
转自https://tech.meituan.com/spark-tuning-pro.html,感谢原作者的贡献 前言 继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作 ...
- Win7 SP1 64位 旗舰版 IE8 快速稳定 纯净优化 无人值守 自动激活 20180604
一.系统特色 1.采用微软原版旗舰版定制而成. 2.优化系统服务,关闭一些平时很少使用的服务. 3.精简掉一些无用的东西. 4.系统全程离线制作,不包含任何恶意插件,放心使用. 5.右下角时间加上星期 ...
- springboot 工程启动报错之Consider defining a bean of type ‘XXX’ in your configuration.
一.前言: 使用springboot自动注入的方式搭建好了工程,结果启动的时候报错了!!!,错误如下图: Description: Field userEntityMapper in com.xxx. ...
- 【2019年04月22日】A股最便宜的股票
太钢不锈(SZ000825) - 当前便宜指数:170.67 - 滚动扣非市盈率PE:4.37 - 滚动市净率PB:0.98 - 动态年化股息收益率:4.79%- 太钢不锈(SZ000825)的历 ...
- C++系统自己主动生成默认构造函数的情况
(1) 基类存在默认构造函数 class CBaseClass { public: CBaseClass() { m_i = 0; } private: int m_i; }; class CDriv ...
- Centos6.8 下 从零开始 部署 Java Web 应用
一.硬件信息 CPU: [root@localhost ~]# grep 'physical id' /proc/cpuinfo | sort -u | wc -l 2 [root@localhost ...
- 如何建立nfs网络文件系统
建立网络文件系统的前提:windows与linux虚拟机及开发板三者之间能够互相ping 通. 三者互ping通IP设置举例: 1. 首先,关闭windows的防火墙,然后通过:ufw disab ...
- word2vec:基本的安装及使用简介
官方word2vec的github下载地址:https://github.com/svn2github/word2vec 环境,linux-ubuntu-14.04LST,安装好git, gcc版本4 ...
- poj 3304
我老人家要开始玩几何了! .这个题有点自闭. 就是问是否存在一条直线经过所有了n条线段,(有交点). 我老人家愚昧不可救药,想了想决定先求出来 这两条直线的交点,然后看是否在线段上.但是一直写不对.. ...
- 更改ORACLE归档路径及归档模式
更改ORACLE归档路径及归档模式 在ORACLE10g和11g版本,ORACLE默认的日志归档路径为闪回恢复区($ORACLE_BASE/flash_recovery_area).对于这个路径, ...