5. Find the minimum k elements (array)
Question: Enter n integers and output the smallest k integers.
For example, if you enter the 8 numbers 1, 2, 3, 5, 6, 7, and 8, the minimum four digits are 1, 2, 3, and 4.
The algorithm has learned the O (n) algorithm for finding small k elements.
I tried to implement the following:
Note that the new method initializes two-dimensional arrays.
int (* a)[5] = new int[8][5];
/* 5. Find the smallest k elements (arrays). Question: Enter n integers and output the smallest k. For example, if you enter the 8 numbers 1, 2, 3, 5, 6, 7, and 8, the minimum four digits are 1, 2, 3, and 4. */# Include <iostream >#include <algorithm> using namespace STD; bool compare (int A, int B) // sort {return A> B in descending order ;} // find the K-small number in array s with n elements in total. In the entire algorithm, all the remaining numbers after dividing by 5 are specially processed int select (int * s, int K, int N) {If (n <5) // perform special processing on fewer than five {sort (S, S + n ); return s [k-1];} 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 ++) {for (Int J = 0; j <5; j ++) {Subs [I] [J] = s [I * 5 + J];} Sort (subs [I], subs [I] + 5, compare ); // five groups in ascending order} For (Int J = 0; j <n % 5; j ++) {Subs [subn-1] [J] = s [subn * 5 + J-5];} Sort (subs [subn-1], subs [subn-1] + N % 5, compare); int * m = new int [subn]; for (INT I = 0; I <subn; I ++ ){ M [I] = Subs [I] [2]; // store the median of each number in m} int Mn = subnn; int M = select (m, mn/2 + (Mn % 2 = 0 )? 0: 1, Mn); Delete [] m; int * S1 = new int [N]; // store the int * S2 = new int [N] numbers smaller than or equal to m; int s1n = 0; // number of records less than or equal to M int s2n = 0; // locate the element for (INT I = 0; I <subnn; I ++) {If (subs [I] [2] <= m) {for (Int J = 0; j <5; j ++) {If (j <2) {If (subs [I] [J] <= m) {S1 [s1n ++] = Subs [I] [J];} else {S2 [s2n ++] = Subs [I] [J] ;}} else {S1 [s1n ++] = Subs [I] [J] ;}} else {for (Int J = 0; j <5; j + +) {If (j> 2) {If (subs [I] [J] <= m) {S1 [s1n ++] = Subs [I] [J];} else {S2 [s2n ++] = Subs [I] [J] ;}} else {S2 [s2n ++] = Subs [I] [J] ;}} if (subnn! = Subn) // extra numeric special processing {for (Int J = 0; j <n % 5; j ++) {If (subs [subn-1] [J]> m) {S2 [s2n ++] = Subs [subn-1] [J];} else {S1 [s1n ++] = Subs [subn-1] [J] ;}}if (k = s1n) {Delete [] S1; Delete [] S2; return m;} else if (k <s1n) {return select (S1, K, s1n);} else {return select (S2, K-s1n, s2n );} delete [] S1; Delete [] S2;} int main () {int A [8] = {1, 2, 4, 5, 6, 7, 8}; int M = select (, 7, 8); Return 0 ;}
However, my code Looks long, so uncomfortable...
It is useful for heap on the Internet. I don't know much about heap. I need to make up some knowledge.
After reading the principle of using the heap method, theoretically it will be a little slower than the algorithm I implement now.
The method is to use the heap to maintain K minimum elements.
From: https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.01.md
Solution 2
Let's further think about it. The question does not require the minimum K number to be ordered, nor the last n-k number to be ordered. In this case, there is no need to sort all elements. At this time, we thought of using selection or exchange sorting, that is:
1. Traverse n numbers and store the K numbers first traversed into an array of K sizes. Assume that they are the minimum K numbers;
2. Find the maximum Kmax among the k elements by selecting or exchanging the order (the maximum value needs to traverse the K number, and the time complexity isO(k)
);
3. Continue to traverse the remaining n-k count. Assume that the value of each new element retrieved is X, and compare X with Kmax: Ifx < kmax
, Replace Kmax with X, and return to the second step to find the maximum element kmax' in the array of k elements. Ifx >= kmax
, The traversal continues without updating the array.
The time used to update or not update the array for each traversal isO(k)
OrO(0)
. The time complexity isn*O(k)=O(n*k)
.
Solution 3
A better solution is to maintain the largest heap with a capacity of K. The principle is similar to solution 2:
- 1. Use the maximum Heap Storage with a capacity of K to store the first K number to be traversed. It is also assumed that they are the minimum K number;
- 2. The elements in the heap are ordered, so that k1 <k2 <... <Kmax (Kmax is set to the largest element in the max heap)
- 3. traverse the remaining n-k count. Assume that the value of the new element retrieved each time is X, and compare X with the Kmax element on the top of the heap: If
x < kmax
, Replace Kmax with X, and then update the heap (logk used); otherwise, the heap is not updated.
The total time complexity is as follows:O(k+(n-k)*logk)=O(n*logk)
. This method is benefited from the time complexity of searching and updating in the heap:O(logk)
(If solution 2 is used: Find the maximum element in the array, time complexity:O(k))
.
Heap implementation code: From http://www.cnblogs.com/panweishadow/p/3632639.html
public static void FindKMin(int[] sort, int k){ int[] heap = sort; int rootIndex = k / 2 - 1; while (rootIndex >= 0) { reheap(heap, rootIndex, k - 1); rootIndex--; } for (int i = k, len=heap.Length; i < len; i++) { if (heap[i]
[Programming question] Find the minimum k Elements