1. 순위 검색
brute-force하게 풀면 5만 * 10만으로 시간초과가 난다. 따라서 다른 방식으로 풀어야 하는 문제.
먼저 주어지는 조건의 경우의 수는 총 120가지(언어3, 직군2, 경력2, 소울푸드2 + 상관없는 경우의 수 + 1씩 해서 4*3*3*3 = 120이지만 예외처리 귀찮아서 4개짜리 길이의 4진수를 구성했고 string 조건을 숫자로 바꾸어 주는 함수를 만들었다. 그리고 조건은 총 4가지, 한 조건씩 "-"(상관없음)으로 바꾸어 가면 한 사람당 총 16개의 경우의 수가 생긴다. 이를 vector에 push한다. 그러면 vector[i]는 조건이 i에 해당하는 사람들의 점수 list가 되고, list를 sort해 두면 binary search할 수 있다.
이어서, query의 조건도 숫자로 바꾸어서 vector[i]에 있는 list를 탐색하고, 이를 binary search(lower bound)해서 나오는 iterator와 vector.end()를 빼서 사람 수를 구할 수 있다. 시간복잡도는 10만 * log(5만)이므로 150만 정도로, 충분히 시간 내에 풀린다.
binary search는 접근도 못했다. 아직 많이 미숙하다. 그리고 모범답안을 보면서 더 부족하단 것을 많이 느꼈다. 조건을 굳이 숫자로 바꿀 필요가 없는게, map<string, vector<int>>을 사용해 버리고 string을 다뤄주면 매번 vector<string>의 백업본을 불러올 필요 없이, 조건에 해당하면 "-"를 string에 넣어버리면 된다..... 분발하자!
// 순위 검색 #include <string> #include <vector> #include <sstream> #include <iostream> #include <algorithm> using namespace std; // 조건을 4진수로 바꿔주는 함수. // 언어 : 1의자리. cpp - 1, java - 2, python - 3, - - 0 // 직군 : 2번째 자리. backend - 1, frontend - 2, - - 0 // 경력 : 3번째 자리. junior - 1, senior - 2, - - 0 // 소울푸드 : 4번째 자리. chicken - 1, pizza - 2, - - 0 // ex. java backend junior pizza : 2112 -> 2 + 4 + 16 + 128 = 150 int conditionToNum(vector<string> v){ int digit = 1, result = 0; string s; for(int i = 0; i<v.size(); i++){ s = v[i]; if(s == "-") result += digit * 0; else if(s == "cpp" || s == "backend" || s == "junior" || s == "chicken") result += digit*1; else if(s == "java" || s == "frontend" || s == "senior" || s == "pizza") result += digit*2; else if(s == "python") result += digit*3; digit *= 4; } return result; } vector<int> changeCondition(vector<string> v){ vector<string> cases = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; vector<string> backup(v.begin(), v.end()); vector<int> result; for(string c : cases){ for(int i = 0; i<4; i++){ v[i] = backup[i]; } for(int i = 0; i<4; i++){ if(c[i] == '1'){ v[i] = "-"; } } result.push_back(conditionToNum(v)); } return result; } vector<int> solution(vector<string> info, vector<string> query) { int num_cases = 256; istringstream iss; string buffer; vector<vector<int>> point_vector(num_cases); // point_vector[i] : 조건이 i인 사람들의 점수 for(string s : info){ iss.clear(); iss.str(s); vector<string> data; while(getline(iss, buffer, ' ')){ data.push_back(buffer); } data.pop_back(); vector<int> all_cases = changeCondition(data); for(int c : all_cases){ point_vector[c].push_back(stoi(buffer)); } } for(vector<int> &v : point_vector){ sort(v.begin(), v.end()); } vector<int> answer; vector<int>::iterator iter; for(string s : query){ iss.clear(); iss.str(s); vector<string> question; while(getline(iss, buffer, ' ')){ if(buffer == "and") continue; question.push_back(buffer); } question.pop_back(); vector<int> target = point_vector[conditionToNum(question)]; iter = lower_bound(target.begin(), target.end(), stoi(buffer)); answer.push_back(target.end() - iter); } return answer; } // simple하게 푼다면, 50,000 * 100,000 = 5,000,000,000 (50억)이므로 시간 초과임. // nlogn으로 풀어라는 문제이다.
2. k진수에서 소수 개수 구하기
진수 변환하고 -> 0으로 string parsing(이 때, buffer에 아무것도 없는 경우 stoi가 되지 않으므로 buffer==""일 때 검사 필요), 이후 숫자들이 소수인지 판정하면 됨. 다만, 이 경우 숫자가 매우 커질 수 있기 때문에 체를 사용하면 메모리 초과가 날 수 있음. 따라서 각 수에 대해 판정하면 될 것.
'PS > PS Log' 카테고리의 다른 글
22.05.05. 풀었던 문제들 (0) | 2022.06.23 |
---|---|
22.05.03. 풀었던 문제들 (0) | 2022.06.23 |
22.05.01. 풀었던 문제들 (0) | 2022.06.23 |
22.04.30. 풀었던 문제들 (0) | 2022.06.23 |
22.04.20. 풀었던 문제들 (0) | 2022.06.23 |