1. 程式人生 > >尋找無序陣列中的第K大數和前K大數

尋找無序陣列中的第K大數和前K大數

兩個問題互相可以轉化。如果可以找到第K大數,那麼只再需要O(N)就可以找齊剩餘的前K大數。如果可以找到前K大數,那麼只再需要O(K)就可以找到第K大數。

先排序,在找第K個。O(NlgN)

快速排序的思想,可以做到平均效率O(N)

隨機選一個元素,把所有小於等於這個元素的數移到左邊,所有大於這個元素的數移動到右邊。如果這個元素成了第K個數,直接返回這個數。

如果左邊的個數大於K,不管右邊的數了,在左邊重複上面的過程。

如果左邊的個數等於T<K,不管左邊的數了,重複上面的過程,只是K=K-T-1。

平均情況下,第一次劃分的時間複雜度是O(N),第二次是O(N/2),總共是O(N+N/2+N/4+...)=O(N)

#include "stdio.h"
#include "stdlib.h"
using namespace std;
const int INCORRECT=-1;

int FindKth(int d[], int left, int right, int k){
	if(left>right)	return INCORRECT;
	else if(left==right&&k!=1) return INCORRECT;
	else if(left==right&&k==1) return d[left];
	else if(k>right-left+1) return INCORRECT;

	int num=d[left];
	int start=left,end=right;
	while(start<end){
		while(start<end&&d[end]>num) end--;
		d[start]=d[end];
		while(start<end&&d[start]<=num) start++;
		d[end]=d[start];		
	}
	d[start]=num;
	int move = start-left + 1;
	if(move==k)
		return d[start];
	else if(move<k)
		return FindKth(d,start+1,right,k-move);
	else
		return FindKth(d,left,start-1,k);
}
int main(){
	int data[10]={1,31,4,52,6,4,77,41,62,94};
	printf("%d\n",FindKth(data,0,9,9));
		
}
所以上對於兩個問題,理論複雜度都可以做到O(N)。

不過實際上,可能存在陣列非常巨大,讀取的次數越少越好。如果K比較小,可以用priority queue來儲存前K的數。這樣只需要讀取一遍陣列就可以,複雜度是O(N+N*lgK)。

如果N非常巨大,且K=N/2,該如何處理?不知道。

相關推薦

尋找無序陣列k大的數——快排思想

找陣列中第k大的數,避免o(n2)時間,考慮快排方法。 #include <iostream> #include <cstdlib> using namespace std; int random_partion(int *p,int n) {

尋找無序陣列K大數K大數

兩個問題互相可以轉化。如果可以找到第K大數,那麼只再需要O(N)就可以找齊剩餘的前K大數。如果可以找到前K大數,那麼只再需要O(K)就可以找到第K大數。 先排序,在找第K個。O(NlgN) 快速排序的思想,可以做到平均效率O(N) 隨機選一個元素,把所有小於等於這個元素

求取一組無序陣列k大的數

方法1.:維持一個大小為k最小堆, 後面來的數小或者等於堆頂元素,則跳過,; 後面來的數大於堆頂元素,堆頂元素彈出,新元素加入最小堆   最後留下的k個數就是,所有數中前k大的數,堆頂元素就是第k大的數 時間複雜度:由於維持大小為k的堆花費時間為log(k),所以時間

無序陣列K大的數

1. 排序法 時間複雜度 O(nlogn) 2. 使用一個大小為K的陣列arr儲存前K個最大的元素 遍歷原陣列,遇到大於arr最小值的元素時候,使用插入排序方法,插入這個元素 時間複雜度,遍歷是 O(n), 插入 O(K), 所以時間複雜度 O(nK) 3. 二叉堆--小頂堆 維護一個有K個元素的

尋找無序陣列K項(分治)

尋找n個數的第K項只需要對它們進行排序,然後找到即可。但是耗時O(nlongn);在書上看到了很好的方法,想著實現一下: 輸入:一個數列A,一個整數K 輸出:數列A中第K小的數   我們假定陣列的一個

求一個無序陣列K小問題

這種問題如果先排序,那麼至少時間複雜度為O(nlogn) 但是有種方法可以達到O(n) 這種方法有個闕值,只有大於44的時候用這種方法才比先排序後查詢的快 首先上一段虛擬碼吧 if(N<44) then 排序A return A[K]; ---O(1) else

python:無序陣列尋找K大的元素

題目: 所謂“第(前)k大數問題”指的是在長度為n(n>=k)的亂序陣列中S找出從大到小順序的第(前)k個數的問題。 解法1:堆排序 採用元素下沉法,維護一個k大小的最小堆,對於陣列中的每一

線性時間複雜度求陣列K大數

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

快速排除(最優法,不是快排)求隨機陣列k大數(c++)(讓數隨機沒寫)

#include <iostream> using namespace std; int get_kth(int arr[], int n, int k) {     int left = 0;     int right = n - 1;     while

無序陣列最大的K個數 或 K大的數

1、方法一:要求無序陣列中沒有重複元素,同時允許更改陣列內的內容。主要思想是利用快速排序Partition函式依次進行前K個元素的排序,平均時間複雜度O(n)。#include <iostream> #include <string> #in

java 實現從無序陣列 找出k大的數, 無序陣列充許有重複元素

要求找出第幾名的元素是什麼(找出B[i]的值)? 找出第k名的元素的值。          先從A中隨機一個下標index1, 然後進行一趟快速排序等到新陣列A1,排完了就知道index1對應的元素在A1中的新下標index2. 如果k等於index2,則A1[index2]就是要找的值。 如果 k小於in

從一個無序陣列求出K大/小的數

這個題目可以作為練習寫大/小根堆的實現,不過貌似時間複雜度還是蠻高的。在洛谷上面一道模板題上面好像就超時了幾個點,不知道是不是我實現的問題。那麼除此之外,最容易想到的方法是先對該陣列進行排序,然後取出第K或MAX-K數來。當選擇使用快排的時候,時間複雜度是$O(nlogn)$。但還有一種更優的方法是利用快排劃

利用快排尋找陣列k個最大元素

/* * 利用快排尋找陣列中第k個最大元素 */ public class FindFirstKElement { //快排 public static int getBaseIndex(int[] arr, int start, int end) { int base = arr[st

leetcode | Median of Two Sorted Arrays 尋找2個有序陣列k大的值

There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time

無序陣列找到k大的數

在N個元素中查詢第K大元素,一般比較簡單的方法就是先快速排序,然後直接返回array[N - K]或者利用掃描法,每一次掃描都找到當前陣列中最大的元素,這個其實就是部分氣泡排序。前一種演算法的時間複雜度是O(NlogN),後一種演算法的時間複雜度是K*N。當然,這裡我們不

無序陣列找到K 大的元素

當然如果我們想要實現這個問題會有很多思路,可以將原來的陣列進行排序即可,直接隨機訪問到第K個元素即可。 我們專門寫一篇部落格當然不是想利用這種思路的,可以試試改進的快速排序啊,對不,我個人覺得是利用了兩種思路一個是快速排序一個是二分查詢,在進行快速排序的時候,在指定範圍內找

尋找陣列k小的數:平均情況下時間複雜度為O(n)的快速選擇演算法

又叫線性選擇演算法,這是一種平均情況下時間複雜度為O(n)的快速選擇演算法,用到的是快速排序中的第一步,將第一個數作為中樞,使大於它的所有數放到它右邊,小於它的所有數放到它左邊。之後比較該中樞的最後位

C:numberNMax 陣列n大數的下標,方法比較笨,應用二級指標

//求陣列中第n大數的下標 int * numberNMax(int * array, int size, int n) { if (NULL==array) { printf("Pointer is NULL\n"); exit(EXIT_FAILURE);

leetcode_陣列k大的元素

215. 陣列中的第K個最大元素 在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出: 5