輸出前m大的數 分治 演算法學習

2021-10-04 06:43:58 字數 1852 閱讀 9372

描述

給定乙個陣列包含n個元素,統計前m大的數並且把這m個數從大到小輸出。

輸入

第一行包含乙個整數n,表示陣列的大小。n < 100000。

第二行包含n個整數,表示陣列的元素,整數之間以乙個空格分開。每個整數的絕對值不超過100000000。

第三行包含乙個整數m。m < n。

輸出

從大到小輸出前m大的數,每個數一行

排序後再輸出,複雜度 o(nlogn)

用分治處理:複雜度 o(n+mlogm)

思路

把前m大的都弄到陣列最右邊,然後對這最右邊m個元素排序,再輸出

引入操作 arrangeright(k): 把陣列(或陣列的一部分)前k大的

都弄到最右邊

一:

如何將前k大的都弄到最右邊

1)設key=a[0], 將key挪到適當位置,使得比key小的元素都在

key左邊,比key大的元素都在key右邊(線性時間完成)

2) 選擇陣列的前部或後部再進行 arrangeright操作

二:

選擇陣列的前部或後部再進行 arrangeright操作

a = k done

a > k 對最右邊a-1個元素再進行arrangerigth(k)

a < k 對左邊b個元素再進行arrangeright(k-a)

關鍵

o(n)時間內實現把前m大的都弄到陣列最右邊

t(n) = t(n/2) + an

= t(n/4) + an/2 + an

= t(n/8) + an/4 + an/2 + an

= …= t(1) + … + an/8 + an/4 + an/2 + an

< 2an

即 o(n)

以上思路來自北大郭偉老師

**

#include

#include

using

namespace std;

#define n 10000+5

int a[n]

;int b[n]

;int n, m;

bool

compare

(int x,

int y)

void

arrangeright

(int l,

int r)

} j--

;swap

(a[j]

, a[l]);

if(n - j == m)

return

;else

if(n - j < m)

arrangeright

(l, j-1)

;else

if(n - j > m)

arrangeright

(j+1

, r);}

intmain()

分治法 前m大的數

給定乙個陣列包含n個元素,統計前m大的數並且把這m個數從大到小輸 出如果先排序再找前m大的,時間複雜度為o nlogn 用分治處理 複雜度 o n mlogm 思路 把前m大的都弄到陣列最右邊,然後對這最右邊m個元素排序,再輸出 關鍵 o n 時間內實現把前m大的都弄到陣列最右邊 如何將前k大的都弄...

輸出前m大的數

o n mlogm n為快排中線性掃瞄時間,mlogm為對m各最大數進行歸併排序耗時 includeusing namespace std int a 100 void swap int a,int b void merge int a,int s,int m,int e,int tmp 歸併 把每...

輸出前m大的數

描述 給定乙個陣列包含n個元素,統計前m大的數並且把這m個數從大到小 輸出。輸入 第一行包含乙個整數n,表示陣列的大小。n 100000。第二行包含n個整數,表示陣列的元素,整數之間以乙個空格分開 每個整數的絕對值不超過100000000。第三行包含乙個整數m。m n。輸出從大到小輸出前m大的數,每...