從「陣列中出現次數超過一半的數字」得到啟發,同樣可以基於partition函式來解決。
一、o(n)演算法
void getleastnumbers(int *input, int n, int *output, int k)
else
}for (int i = 0; i < k; ++i)
output[i] = input[i];
}
二、o(nlogk)演算法
可以先建立乙個大小為k的資料容器來儲存最小的k個數字,姐下來我們每次從輸入的n個整數中讀入乙個數。如果容器中已有的數字少於k個,則直接把這次讀入的整數放入容器中;如果容器中已有k個數,也就是容器已滿,此時我們不能再插入新的數字而只能替換已有的數字。找出這已有的k個數的最大值,然後拿這次待插入的整數和最大值進行比較。如果待插入的值比當前已有的最大值還要大,那麼直接丟棄。
很容易想到最大堆,於是我們每次可以在o(1)得到已有的k個數字的最大值,但需要o(logk)時間完成刪除及插入操作
// 「下沉」,位置pos處開始
void sink(int pos, int a, int n)
}
// array:輸入陣列
// a[0]未用
fori = 0 to k
a[i+1] = array[i]
end for
// 建立大根堆:將陣列中的前k個元素構建成乙個最大堆
void buildheap(int a, int k) // k個元素,完全二叉樹儲存
}
// 陣列後面的元素,往最大堆插入(待插元素比堆頂元素小) 或者 丟棄(待插元素大於堆頂元素)
fori = k + 1 to n
ifarray[i] < a[1]
a[1] = array[i]
sink(1, a, k)
end if
end for
二、利用stl set和multiset(允許重複)底層基於紅黑樹實現的機制
typedef multiset> intset; // 按從大到小排序
typedef multiset>::iterator setiterator;
void getleasetnumbers(const vector&data, intset &leastnumbers, int k)}}
}
最小的K個數
問題描述 給定的n個整數,計算其中最小的k個數。最直觀的解法莫過於將n個數按公升序排列後輸出前k個。但是就效率來看,這種方法並不是最理想的。一種改進方法是借助快速排序中對陣列的劃分,以第k個元素對陣列進行劃分,使得比第k個數字小的數字都在其左邊,比其大的數字都在它的右邊。void swap int ...
最小的K個數
輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,如果不讓使用sort的話,自己實現乙個,或者依次選取最小的 class solution public vectorgetleastnumbers solution vectori...
最小的K個數
輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,基本方法 思路一 在k個數的陣列中多次排序,每次替換掉最大的,直到原陣列中的數比較完 vectorgetleastnumbers solution vectorinput,int ...