1. 程式人生 > 其它 >L1-020 帥到沒朋友 (20 point(s))

L1-020 帥到沒朋友 (20 point(s))

  • 最開始用了 set 但最後一個測試點超時了,想了想這遍歷是順序的,不需要考慮排序,所以用了 unordered_set 就把最後一個測試點給解決了。

    而想了想既然 unordered_set 都可以,那麼類似的向量 vector 也應該是可以的,所以就改成向量試了試。但結果發現卻超時了。

    故查了查這兩個容器的比較。向量是 vector 線性表,而 unordered_set 是hash容器。而在該題後面我用到了多個 find 來搜尋朋友圈中是否有該人的存在。

    故在查詢效率下,顯然 vector 只能線性查詢,時間複雜度是 O(n) ,而 unordered_set 根據對映關係時間複雜度是 O(1) 所以前者的超時就可以理解了。

    集合求交集中,vector, set ,unordered_set,的對比試驗

  • 寫 vector 的 find 函式時報錯,所以查了下該容器的 find 怎麼寫。發現 vector 的 find 不是成員而是靜態函式,並且還需要傳入容器的起始末尾地址以確定範圍。

    寫了之後就可以發現整個 find 程式碼十分冗長,所以還是用回 unordered_set 較好。而且用 vector,還會超時。

    vector中find和find_if的用法

  • 參考了別人的方法,又發現了很多神奇的東西。

    因為題目說了,“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";
}