ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

关于中位数的问题 implemented by C++

2019-08-19 22:01:53  阅读:314  来源: 互联网

标签:end ba median 中位数 C++ start 序列 implemented


文章目录

中位数

对于一个有序序列来说,很简单,如果长度为 nnn 的话,那么中位数就是序列中 n/2n/2n/2 位置的数组元素了

一个序列的中位数

如果:

  • 这是一个有序的序列,那么非常简单,不再多说
  • 如果这不是一个有序序列,那么我们自然会这样想:先对序列进行排序再找到中位数,而这样的算法的复杂度其实就是排序算法的复杂度了(可以考虑快速排序,或者是用一个大小为序列大小一半的堆进行堆排序

两个序列的中位数

合并序列找到中位数

如果我们希望找到两个有序序列的中位数的话,很快我们就可以想到,merge lists then find the median,将两个序列合并然后再找到中位数,这样的算法的复杂度自然就是序列合并算法的复杂度了,设两个序列的长度分别为m和n:
(0)O(N)=O(min(m,n)) O(N) = O(min(m, n)) \tag{0} O(N)=O(min(m,n))(0)
显然,这样的算法的复杂度就是 O(n)O(n)O(n),n的一次方的复杂度。这样我们自然会想到:我们能不能想到一个算法的复杂度是 logn\log{n}logn 呢?答案是肯定的。

不合并序列

基本思想

分别找到两个序列 A,BA,BA,B 的中位数a,ba,ba,b,然后:

  • 如果 a=ba=ba=b ,则这个值即所求中位数
    这是很好理解的,如果两个序列的中位数相同,那么合并的升序序列的中间依然会是这两个数,所以这就是所求中位数
  • 如果 a>ba>ba>b ,则保留 AAA 的前半段和 BBB 的后半段
    合并的升序序列的中位数必然在这两段之中。如果不在,假设中位数 ccc 在A的后半段,那么,ccc 一定大于A的前半段的所有元素,并且大于B的前半段的所有元素,也就是说, 此时 ccc 的值已经大于合并序列的一半元素了,再加上 a,ba,ba,b 这两个元素,那么,ccc 至少大于合并序列一半以上的元素,不符合中位数的定义。同理在 BBB 的前半段我们也可以这样证明
  • 否则,a&lt;ba &lt; ba<b ,则保留 AAA 的后半段和 BBB 的前半段

重复以上过程,直到两个序列都只剩下一个元素,较小的一个即为中位数。

C++实现

我们还需要注意的是序列长度的奇偶性(partiality),我们需要根据序列长度确定是否要保留原来序列的中间点。
对于偶数,你可以简单的考虑剩下两个元素的情况,这个时候中间点就是第一个元素,那么自然的:

  • 如果要保留前半段,那么肯定得包含中位数,否则前半段为空了,而此时我们肯定希望保留剩下一个元素,所以此时必须包括中间点
  • 如果要保留后半段,那么自然就是不包括中间点了
    而对于奇数,很显然我们必须保留中间点,因为它仍有可能是最终的中位数,所以不管是前半段还是后半段都要保留中间点。
// ptr for starts and ends during the very iteration
int start_A = 0, end_A = length - 1, start_B = 0, end_B = length - 1;
int median_A = 0, median_B = 0;
// iterations
while(start_A != end_B && start_B != end_B){
	// get medians' position
	median_A = (start_A + end_A) / 2;
	median_B = (start_B + end_B) / 2;
	if(A[median_A] == B[median_B]){
		std::cout << A[median_A] << std::endl;
	}
	else if(A[median_A] > B[median_B]){
		if((end_A - start_A)%2 == 0){
			end_A = median_A;
			start_B = median_B + 1;
		}
		else{
			end_A = median_A;
			start_B = median_B;
		}
	}
	else{
		if((end_A - start_A)%2 == 0){
			end_B = median_B;
			start_A = median_A + 1;
		}
		else{
			end_B = median_B;
			start_A = median_A + 1;
		}
	}
}
std::cout << A[median_A] <= B[median_B]?A[median_A]:B[median_B] << std::endl;

标签:end,ba,median,中位数,C++,start,序列,implemented
来源: https://blog.csdn.net/Lyn_B/article/details/99635047

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有