程式設計題目 查詢最小的 k 個元素

2022-05-18 11:00:51 字數 2935 閱讀 1273

5.查詢最小的 k 個元素(陣列)

題目:輸入 n 個整數,輸出其中最小的 k 個。

例如輸入 1,2,3,4,5,6,7 和 8 這 8 個數字,則最小的 4 個數字為 1,2,3 和 4。

演算法裡面學過查詢第k小的元素的o(n)演算法

試著實現了一下:

注意new 初始化二維陣列的方式 

int (* a)[5] = new int[8][5];
/*

5.查詢最小的 k 個元素(陣列)

題目:輸入 n 個整數,輸出其中最小的 k 個。

例如輸入 1,2,3,4,5,6,7 和 8 這 8 個數字,則最小的 4 個數字為 1,2,3 和 4。

*/#include

#include

using

namespace

std;

bool compare(int a, int b) //

降序排列

//找到 一共有 n個 元素的 陣列s 中 第k小 的數字 整個演算法中,對除以5後餘下的數字都做了特殊處理

int select(int * s, int k, int

n)

int subn = n/5 + ((n % 5 == 0) ? 0 : 1

);

int subnn = n/5

;

int (* subs)[5] = new

int[subn][5

];

for (int i = 0; i < subnn; i++)

sort(subs[i], subs[i] + 5, compare); //

5個一組,每組從大到小排序

}

for (int j = 0; j < n % 5; j++)

sort(subs[subn - 1], subs[subn - 1] + n % 5

, compare);

int * m = new

int[subn];

for (int i = 0; i < subn; i++)

int mn =subnn;

int m = select(m, mn/2 + (mn % 2 == 0) ? 0 : 1

, mn);

delete m;

int * s1 = new

int [n]; //

存放小於等於m的數字

int * s2 = new

int[n];

int s1n = 0; //

記錄有多少小於等於m的數字

int s2n = 0

;

//找到相應的s1 與 s2中的元素

for (int i = 0; i < subnn; i++)

else

}else}}

else

else

}else}}

}if (subnn != subn) //

多餘的數字特別處理

else}}

if (k ==s1n)

else

if (k else

delete s1;

delete s2;

}int

main()

;

int m = select(a, 7, 8

);

return0;

}

不過,我的**看起來好長,好難受啊...

網上有用堆做的,對堆不是很了解,要補一下知識。

看了用堆的方法的原理,理論上會比我現在實現的這個演算法慢一點

方法是用堆維護k個最小元素

下面來自:

咱們再進一步想想,題目沒有要求最小的k個數有序,也沒要求最後n-k個數有序。既然如此,就沒有必要對所有元素進行排序。這時,咱們想到了用選擇或交換排序,即:

1、遍歷n個數,把最先遍歷到的k個數存入到大小為k的陣列中,假設它們即是最小的k個數;

2、對這k個數,利用選擇或交換排序找到這k個元素中的最大值kmax(找最大值需要遍歷這k個數,時間複雜度為o(k));

3、繼續遍歷剩餘n-k個數。假設每一次遍歷到的新的元素的值為x,把x與kmax比較:如果x < kmax,用x替換kmax,並回到第二步重新找出k個元素的陣列中最大元素kmax『;如果x >= kmax,則繼續遍歷不更新陣列。

每次遍歷,更新或不更新陣列的所用的時間為o(k)o(0)。故整趟下來,時間複雜度為n*o(k)=o(n*k)

更好的辦法是維護容量為k的最大堆,原理跟解法二的方法相似:

這樣下來,總的時間複雜度:o(k+(n-k)*logk)=o(n*logk)。此方法得益於堆中進行查詢和更新的時間複雜度均為:o(logk)(若使用解法二:在陣列中找出最大元素,時間複雜度:o(k))

堆的實現**:來自

public

static

void findkmin(int sort, intk)

for (int i = k, len=heap.length; i < len; i++)

}console.writeline(

"the min element =

",k);

for (int i = 0; i < k; i++)

} private

static

void reheap(int heap, int rootindex, int

lastinddex)

}if (orphan else

}heap[rootindex] =orphan;

}

查詢最小的k個元素

題目 輸入n個整數,輸出其中最小的k個。演算法思想,要是將n個數排序然後輸出前k個,方法很簡單,但計算量比較大,為o nlogn 要是新建乙個有k個元素陣列,在陣列不滿時,將每乙個輸入的資料存入陣列。若陣列滿了,則比較輸入的資料與陣列中最大元素的大小,來決定接下來幹什麼,接下來幹什麼,我語言表達能力...

查詢最小的k個元素

查詢最小的k個元素 題目 輸入n個整數,輸出其中最小的k個。例如輸入1,2,3,4,5,6,7和8這8個數字,則最小的4個數字為1,2,3和4。1 輸入元素,並排序 2 輸出前k個元素 排序 採用高效的排序方法,如 快速排序,歸併排序等 方法一 採用最簡單的方法 include include in...

查詢最小的k個元素

題目 輸入n個整數,輸出其中最小的k個數 例如 1 2 3 4 5 6 7 8 這8個數字,則最小的4個數字為1,2,3,4,第一種 直接對其先排序,再取頭幾個數 這樣最快是nlogn 快排或者堆排 include using namespace std void partsort int a,in...