L1-020 帥到沒朋友 (20 point(s))
-
最開始用了 set 但最後一個測試點超時了,想了想這遍歷是順序的,不需要考慮排序,所以用了 unordered_set 就把最後一個測試點給解決了。
而想了想既然 unordered_set 都可以,那麼類似的向量 vector 也應該是可以的,所以就改成向量試了試。但結果發現卻超時了。
故查了查這兩個容器的比較。向量是 vector 線性表,而 unordered_set 是hash容器。而在該題後面我用到了多個 find 來搜尋朋友圈中是否有該人的存在。
故在查詢效率下,顯然 vector 只能線性查詢,時間複雜度是 O(n) ,而 unordered_set 根據對映關係時間複雜度是 O(1) 所以前者的超時就可以理解了。
-
寫 vector 的 find 函式時報錯,所以查了下該容器的 find 怎麼寫。發現 vector 的 find 不是成員而是靜態函式,並且還需要傳入容器的起始末尾地址以確定範圍。
寫了之後就可以發現整個 find 程式碼十分冗長,所以還是用回 unordered_set 較好。而且用 vector,還會超時。
-
參考了別人的方法,又發現了很多神奇的東西。
因為題目說了,“K超過1的朋友圈裡都至少有2個不同的人” 所以在處理的時候 K == 1 的朋友圈說明只有物件自己,這種朋友圈即不需要讀取也不需要處理。固有如下程式碼。
for (int i = 0; i < K; ++i) { cin >> id; if (K > 1) mp[id]++; }
而在統計了每個人朋友圈的數量後,因為所統計的朋友圈必然包括除自己的其他物件,所以存在一個朋友圈就說明該物件必然有朋友,反之朋友圈數量為 0 的就說明必然沒有朋友。
if (mp[id]++ == 0) cout << (flag++ ? " " : "") << id;
可以看到程式碼對朋友圈數量進行了判斷,同時可以看到在判斷裡面對 mp[id] 進行了 ++ 運算,因為條件 “同一個人可以被查詢多次,但只輸出一次” 所以為了避免再次查詢而輸出,所以給這個物件朋友圈 ++ 防止再次輸出。
還有是最後輸出 “No one is handsome” ,在列印空格的時候我們用了變數 first 來標記是第一個輸出還是第n個輸出。所以在後面判斷是否有帥哥的時候,我們除了用容器來記錄和判斷之外,也可以用 first 來判斷。
如果 first == 0 那麼必然說明輸出為 0 沒有帥哥。
-
再記錄一個問題,如果用了 if(K > 1) 來統計,那麼就不能夠用 while(K--) 來作為迴圈判斷,不然 K-- 會讓 if(K > 1) 判斷不成立而錯誤,所以需要改成下面的程式碼。
for(int i = 0; i < K; i++)
所以可以看到,當迴圈變數既用於判斷迴圈邊界又用於自增自減來迴圈判斷的時候,是不能夠在其他地方用這個迴圈變數作為判斷依據的,因為判斷是靜態的,如果又用了自增自減顯然就是動態的,就會跟事實不符。
// 參考後的精簡程式碼
#include <bits/stdc++.h>
using namespace std;
int main(){
int N, K, M, first = 0;
string id;
map<string, int> Moments;
cin >> N;
while(N--){
cin >> K;
for(int i = 0; i < K; i++){
cin >> id;
if(K > 1)
Moments[id]++;
}
}
cin >> M;
while(M--){
cin >> id;
if(Moments[id]++ == 0)
cout << (first++ ? " " : "") << id;
}
if(first == 0) cout << "No one is handsome";
}
// unordered_set 20 points
#include <bits/stdc++.h>
using namespace std;
int main(){
int N, K, M, first = 0;
vector<unordered_set<string>> Moments;
// 讀取朋友圈
cin >> N;
for(int i = 0; i < N; i++){
unordered_set<string> tmp;
string str;
cin >> K;
while(K--){
cin >> str;
tmp.insert(str);
}
Moments.push_back(tmp);
}
// 輸出標記
set<string> isPrint;
// 查詢
cin >> M;
while(M--){
bool out = true;
string str;
cin >> str;
// 從每個朋友圈中尋找
for(int i = 0; i < N; i++){
// 找到朋友則結束尋找 不輸出
if(Moments[i].size() > 1 && Moments[i].find(str) != end(Moments[i])){
out = false;
break;
}
}
// 遍歷完都找不到說明是帥哥 && 該人沒有輸出過
if(out == true && isPrint.find(str) == end(isPrint)){
cout << (first++ ? " " : "") << str;
isPrint.insert(str);
}
}
if(isPrint.size() == 0) cout << "No one is handsome";
}
// vector 17points 錯誤示範
#include <bits/stdc++.h>
using namespace std;
int main(){
int N, K, M, first = 0;
vector<vector<string>> Moments;
// 讀取朋友圈
cin >> N;
for(int i = 0; i < N; i++){
vector<string> tmp;
string id;
cin >> K;
while(K--){
cin >> id;
tmp.push_back(id);
}
Moments.push_back(tmp);
}
// 輸出標記
vector<string> isPrint;
// 查詢
cin >> M;
while(M--){
bool out = true;
string id;
cin >> id;
// 從每個朋友圈中尋找
for(int i = 0; i < N; i++){
// 找到朋友則結束尋找 不輸出
if(Moments[i].size() > 1 &&
find(begin(Moments[i]), end(Moments[i]), id) != end(Moments[i])){
out = false;
break;
}
}
// 遍歷完都找不到說明是帥哥 && 該人沒有輸出過
if(out == true &&
find(begin(isPrint), end(isPrint), id) == end(isPrint)){
cout << (first++ ? " " : "") << id;
isPrint.push_back(id);
}
}
if(isPrint.size() == 0) cout << "No one is handsome";
}