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

2021-07-26 21:25:00 字數 1416 閱讀 7295

尋找n個數的第k項只需要對它們進行排序,然後找到即可。但是耗時o(nlongn);在書上看到了很好的方法,想著實現一下:

輸入:乙個數列a,乙個整數k

輸出:數列a中第k小的數  

我們假定陣列的乙個數v,現在把陣列a分成三份。

a2 =

a3= }

例如任意乙個陣列a=;

假設v等於5     a1=2 4 1 ;      a2=5 5;       a3=36  21  8  13  11 20

搜尋範圍就減小了。現在只需要在a的三個子集中尋找,如果想尋找第8小元素,他一定在a3中,同理可以得到遞迴

f(a1,v)    if  k<=|a1|

f(a,k)= printf(a2)   if  k==|a1+a2|

f(a3,v-|a1|-|a2|)   if  k>|a1+a2|

思路清晰後,重要的是v的選取,因為v的選取決定了整個演算法的複雜度。最理想的情況就是|a1|,|a3|=1/2|a|

如果我們一直背運,我們選出來的v很可能一直是陣列的最大元素或者最小元素,那麼演算法需要執行

n+(n-1)+(n-2)+....+n/2=o(n*n)

但是這種情況出現的概率非常低

最好的情形是選取的v正好能把陣列一分為二,從而複雜度為o(n)

從o(n)->o(n*n) 演算法的平均執行時間基本符合最佳執行時間

當然**肯定有瑕疵。才接觸分治  又不好的地方大家一起交流下

#include#includeusing namespace std;

void f(int a, int zuo, int you, int v)

//system("pause");

//printf("\n");

int a1[10] = , a2[10] = , a3[10] = ;

int num = v / 2;

int j = 0, k = 0, l = 0;

for (int i = zuo; i <= you; i++)

if (v <= j)

else if (v>j&&v<=k+j)

else if (v > j + k)

}int main();

int b[10] = ;

//int n = 8;

int k;

//scanf("%d", &k);

printf("偶數的第n小的值分別為:\n");

for (int k = 1; k <= 8;k++)

f(a, 0, 7,k);

printf("\n奇數的第n小的值分別為:\n");

for (int k = 1; k <= 9; k++)

f(b, 0, 8, k);

return 0;

}

尋找單個無序陣列中第K小的數字

1 排序 對陣列進行排序 然後前k個元素就是需要查詢的元素,排序的方法可以採用快速排序,但是我們知道在快速 排序中如果已經是有序的陣列,採用快速排序的時間複雜度是o n 2 為了解決這種問題,通常選擇隨機選擇乙個 陣列值pivot作為基準,將陣列分為s1 pivot和s2 pivot,這樣就能避免快...

快速排序 尋找無序陣列中的第k大的數

思路是利用快速排序 因為快速排序的分治思想可以將查詢的範圍縮小 快速排序的思想 low為陣列的起始點,high為陣列的尾部點。交替掃瞄 1.固定陣列的第乙個數為定點,從陣列的尾部high開始往左查詢,直到第乙個比定點小的數,和定點交換,因此當前點為空 high 2.從陣列的起始處,low找到第乙個比...

尋找無序陣列的中位數

題目 求乙個無序陣列的中位數。如 的中位數為5,的中位數為4和5。void findmidnum1 int arr,int size for int j size 1 2 1 j size j if size 1 奇數個元素 cout 中位數 pq.top endl else 1.將陣列元素平均分配...