PS/PS Log
23.09.23. 풀었던 문제들
hyelie
2023. 9. 25. 03:02
Programmers Lv. 3 불량 사용자, 28분
문제 자체는 주어진 것만 풀면 되는 문제. input size가 8이므로 최대 8!의 시간 복잡도이며, 따라서 backtrack(순열)로 풀면 된다.
단, 유의할 점은 `제재 아이디 목록을 구했을 때 아이디들이 나열된 순서와 상관없이 아이디 목록의 내용이 동일하면 같은 것으로 처리한다`이기 때문에, 이를 잘 처리해야 한다.
- 모든 banned_id에 대해 가능한 user_id의 후보군들을 나열하고,
- permutation/backtrack으로 가능한 모든 조합을 나열하고,
- 해당 조합에서 겹치는 것을 빼면 되겠네.
위 3가지 flow로 쉽게 처리할 수 있다.
// banned_id와 user_id가 일치하는지
bool isBanned(string banned_id, string user_id){
if(banned_id.length() != user_id.length()) return false;
int len = banned_id.length();
for(int i = 0; i<len; i++){
if(banned_id[i] == user_id[i] || banned_id[i] == '*') continue;
// 실수 1. banned_id[i] == '*'로 했어야 했는데 user_id[i] == '*'로 했다.
else return false;
}
return true;
}
set<string> answer;
unordered_map<string, bool> visited; // visited[i] : user_id[i]를 사용했는지 여부. true then used
vector<vector<int>> candidates; // candidites[i] : banned_id[i]가 적용될 수 있는 user_id index vector
vector<string> user_ids, banned_ids;
void backtrack(int cur_depth, int max_depth, string result){
if(cur_depth == max_depth){
sort(result.begin(), result.end());
answer.insert(result);
return;
}
for(int i = 0; i<candidates[cur_depth].size(); i++){
int user_idx = candidates[cur_depth][i]; // 실수 4. user_idx를 i로 넣었다.
string s = user_ids[user_idx];
if(!visited[s]){ // 실수 2. visited 로직을 뺐다.
visited[s] = true;
backtrack(cur_depth + 1, max_depth, result + to_string(user_idx)); // 실수 5. user_idx가 아니라 i로 넣었다.
visited[s] = false;
}
}
return;
}
int solution(vector<string> uids, vector<string> bids) {
// init
user_ids = uids;
int user_size = user_ids.size();
for(string user_id : user_ids){
visited[user_id] = false;
}
banned_ids = bids; // 실수 3. uid로 넣었다.
int banned_size = banned_ids.size();
candidates.resize(banned_size);
// init candidates
for(int i = 0; i<banned_size; i++){
for(int j = 0; j<user_size; j++){
if(isBanned(banned_ids[i], user_ids[j])){
candidates[i].push_back(j);
}
}
}
backtrack(0, banned_size, "");
return answer.size();
}
시간복잡도
O(8!)
후기
오랜만에 풀어서? 그런가, 너무 급하게 풀려 해서 그런가, 실수가 너무 많았다.