找前n個最大數
假設有10000個數,需要找到裏面前10個最大數。
樸素的解法當然是先排序,然後輸出前10 個數,時間複雜度最低爲O(logn)。
思考我們可以維護一個10個元素大小的容器,用在某種算法使得這個容器裏面維護的就是我們需要的10個數。
先從vector開始思考,用前10和數初始化,然後不斷的遍歷剩餘元素,找到一種條件使得可以將新遍歷得到的數字加入到vector中,爲使得vector保存的是前10個最大的元素,則如果某一次遍歷得到的元素大於vector中最小元素,則可以將該元素與vector中的最小元素做替換。爲了達成這一目的,我們需要維護一個vector最小元素的變量,並需要在發生替換時進行更新。
vector雖然可以滿足這一想法的實現,但並不是十分的高效,既然我們每一次都需要將容器中的最小元素和另一個元素交換,不如用小頂堆來實現,最小元素必在堆頂,比較和替換都很容易。
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<functional>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> vec{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
priority_queue<int, vector<int>, greater<int>> pq(vec.begin(), vec.begin() + n);
for (int i = n; i < vec.size(); i++)
{
if (vec[i] > pq.top())
{
pq.push(vec[i]);
pq.pop();
}
}
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
return 0;
}
生成100個不重複的隨機數
簡單思路,不斷的取隨機數,已存在結果集合內則跳過,否則加入結果數組,需要用到哈希表來節省時間,而且效率很低。
既然要求不重複,我們不妨直接先生成100個不同的數字,存放在集合vec中,然後找到一種思路從vec中取數字加入如果數組res,直接思路可以不斷的生成隨機數,以該數爲索引從vec中取數,若該數已經取走,則跳過,這樣還是效率不高。因此我們思考一種每一次都要取到數的方法,將每次生成的隨機數取模vec的大小,每次取數之後都將取到的數從vec中刪除。
#include<iostream>
#include<vector>
#include<algorithm>
#include<random>
#include<ctime>
using namespace std;
int main() {
vector<int> vec(100), res;
for (int i = 0; i < 100; i++)
vec[i] = i;
/*default_random_engine rengine;
uniform_int_distribution<int> dist;*/
int n = 100;
while (n)
{
//int curr = dist(rengine) % n;
srand(int(time(0)));
int curr = rand() % n;
res.push_back(vec[curr]);
vec.erase(vec.begin() + curr);
n--;
}
for (auto &a : res)
cout << a << " ";
return 0;
}