最强解析面试题:在无序数组中取最大的K个数「建议收藏!」

Posted 魏小言

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最强解析面试题:在无序数组中取最大的K个数「建议收藏!」相关的知识,希望对你有一定的参考价值。


这是面试中最大概率会问的一道题,总结之前的面经,总结如下:

方法一

一、当无序数组元素个数数量级不高的情况下,对数组进行排序,如果用最快的排序快速排序,时间复杂度为O(nlogn),排序结束后取其前K个元素,时间复杂度为常量,总体时间复杂度为O(nlogn)。

这是最容易想到的解决方法。但要求取前K个最大元素,并没有要求其有序,在上述方法中,是对数组所有元素进行了排序的,包括N-K、和K个元素。这样的话就可以,采取选择排序或者交换排序对数组进行部分排序,直接排出最大的K个元素。

方法二

二、选择排序:对数组进行选择排序,时间复杂度为O(n*k)。

1,2相比来说,在K>logN 的情况下,选择1,方法比较好,反之。

无序数组元素数量级很大时,机器内存不能一次运算时,可以采取最大堆的方式,当加入堆中有K个元素时,即为最大的K个元素;在不断向堆中加元素时,将其与原堆中的最小值比较,如果大于,则交换,内存中永远只有堆的空间。

举例:寻找 N 个数中最大的 K 个数,本质上就是寻找最大的 K 个数中最小的那个,也就是第 K 大的数。可以使用二分搜索的策略来寻找 N 个数中的第 K 大的数。对于一个给定的数 p,可以在 O(N)的时间复杂度内找出所有不小于 p 的数。假如 N 个数中最大的数为 Vmax,最小的数为 Vmin,那么这 N 个数中的第 K 大数一定在区间[Vmin, Vmax]之间。那么,可以在这个区间内二分搜索 N 个数中的第 K大数 p。

伪代码如下:

while(Vmax-Vmin > delta)
{
Vmid = Vmin + (Vmax – Vmin) * 0.5;
if(f(arr, N, Vmid) >= K)
Vmin = Vmid;
else
Vmax = Vmid;
}

伪代码中 f(arr, N, Vmid)返回数组 arr[0, …, N-1]中大于等于 Vmid 的数的个数。

上述伪代码中,delta 的取值要比所有 N 个数中的任意两个不相等的元素差值之最小值小。如果所有元素都是整数,delta 可以取值 0.5。循环运行之后,得到一个区间(Vmin, Vmax),这个区间仅包含一个元素(或者多个相等的元素)。

方法三

另一种方法是,找出最大K个元素中的最小值,然后进行时间复杂度为O(n)的操作,找出比最小值大的K个元素。但前提是了解数组元素的最大值和最小值。在寻找最大K个元素中的最小值时,采用二分法查找即可。

if(X > h[0])
		{
			h[0] = X;
			p = 0;
			while(p < K)
			{
				q = 2 * p + 1;
				if(q >= K)
					break;
				if((q < K-1) && (h[q + 1] < h[q]))
					q = q + 1;
				if(h[q] < h[p])
				{
					t = h[p];
					h[p] = h[q];
					h[q] = t;
					p = q;
				}
				else
					break;
			}
		}

另外在数组元素范围有限的情况下,也可以直接使用计数排序。

for(sumCount = 0, v = MAXN-1; v >= 0; v–)
		{
			sumCount += count[v];
			if(sumCount >= K)
				break;
		}
return v;

  注意:计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。

最强总结

  它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。
  [1-2] 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)

附录

一天一个小技巧,偷偷超越隔壁老大哥!

欢迎加入群聊【编程技术交流分享群Q:717647116】,微信群请私信博主添加

以上是关于最强解析面试题:在无序数组中取最大的K个数「建议收藏!」的主要内容,如果未能解决你的问题,请参考以下文章

最强解析面试题:在无序数组中取最大的K个数「建议收藏!」

最强解析面试题:最小 K 个数

最强解析面试题:二进制中 1 的个数「建议收藏!炸!」

最强解析面试题:二进制中 1 的个数「建议收藏!炸!」

最强解析面试题:链表中倒数第 k 个节点「建议收藏!」

最强解析面试题:链表中倒数第 k 个节点「建议收藏!」