반응형
cpp(C++)로 풀었으니 참고.
카카오 기출을 한 번 풀어야겠다고 마음 먹고 처음 접한 문제다. 그냥 이름 재밌어보이는거로 잡았는데 하필이면 난이도: 상 짜리.. 눈물나게 고민하고 풀었다. 하루종일 생각했다. 솔직히 처음에 감이 안잡혀서 카카오 공식 홈페이지에 해설을 간단하게 읽어본 후 많은 고민 끝에 구현할 수 있었다.. (그러니까 후딱 안풀린다고 절대 좌절하지 말자!)
크게 아래와 같은 로직으로 생각했다.
- 대전제로 먼저 모든 시간은 millisecond 단위로 변환하자. 그렇다고 해도 int 범위안에 넉넉하게 담을 수 있으니 ok
- 각 로그 문자열마다 순회를 하면서 먼저 string을 시간으로 변환한다. 아래는 각 로그 문자열string처리 로직이다.
- 로그 문자열의 종료 시간(endTime)을 먼저 millisecond로 환산해서 구한다.
- 로그 문자열의 시작 시간(startTime)을 구한다. 앞서 구한 종료 시간(endTime)과 파싱한 경과 시간(elapsedTime)을 이용하여 구할 수 있다.
- 위에서 처리한 문자열을 pair<int, int>에 <시작 시간(startTime), 종료 시간(endTime)> 순으로 저장하자.
- 이제 이 pair를 순회하면서 각 pair 마다 (종료 시간 - 1ms) ~ (종료 시간 -1ms + 1000ms(1초)) 기준 구간을 잡아 준 후, 모든 pair의 각 기준 구간에 대해 모든 pair들을 순회하면서 그 기준 범위 안에 들어가있는지 카운트 해준다. 즉, 시간 복잡도는 로그 문자열의 길이가 N이라면 O(N^2) 을 갖게 될 것이다.
- 이렇게 구한 카운트의 최대값을 출력해주면 정답이 된다.
내 생각에 여기서의 포인트는 4번이다. 1초 범위로 스냅샷을 찍었을 때 가장 처리가 많이 되고 있는 구간을 찾는 문제인데, 그 스냅샷을 찍는 범위를 어떻게 할지가 관건이라고 생각한다. 1ms 로 이동하면서 1초 범위를 계속 잡는다면 24시간동안 1ms * 1000 * 60 * 60 * 24 = 86,200,000 가지의 범위에 대해 모두 계산을 해야 하므로 비효율적이다. 따라서 각 로그 문자열의 종료 시간을 기준으로 거기보다 1ms 적은 값을 시작시간으로 해두고 1초 간의 범위를 생각하면, 86,200,000개가 아닌 로그 문자열의 개수만큼의 범위만 고려하면 되는 것이다. 범위를 막대로 직접 그리면서 생각하다 보면 이해가 갈 것이다.
#include <string>
#include <vector>
using namespace std;
int getStartTime(int &endTime, string &line){
int startTime = 0;
string tmp = line.substr(24); tmp.pop_back();
int elapsedTime = stod(tmp.c_str())*1000;
startTime = endTime - elapsedTime + 1;
return startTime;
}
int getEndTime(string &tmp){
int endTime = 0;
int hours = atoi(tmp.substr(0,2).c_str())*60*60*1000;
int minutes = atoi(tmp.substr(3,2).c_str())*60*1000;
int seconds = atoi(tmp.substr(6,2).c_str())*1000;
int milliseconds = atoi(tmp.substr(9,3).c_str());
endTime = hours + minutes + seconds + milliseconds;
return endTime;
}
vector<pair<int,int>> timeParse(vector<string> &lines){
vector<pair<int,int>> times;
for(int i = 0; i < lines.size(); ++i){
string tmp = lines[i].substr(11,12);
int endTime = getEndTime(tmp);
int startTime = getStartTime(endTime, lines[i]);
times.push_back(make_pair(startTime, endTime));
}
return times;
}
int solution(vector<string> lines) {
int answer = 0;
vector<pair<int,int>> times = timeParse(lines);
for(int i = 0; i < times.size(); i++){
int rangeStart = times[i].second - 1;
int rangeEnd = rangeStart + 1000;
int count = 0;
for(int j = 0; j < times.size(); ++j){
if(times[j].first <= rangeEnd && times[j].second >= rangeStart){
count++;
}
}
if(count > answer) answer = count;
}
return answer;
}
source code: https://github.com/brwnsugr/algorithm/blob/master/kakao_test/2018_1st_thanksgiving_traffic.cpp
반응형
'알고리즘_개념 및 문제풀이 ' 카테고리의 다른 글
BOJ 그리디 문제 모음2/C++/30(#10610)/병든나이트(#1783)/NMK(#1201) (0) | 2020.03.23 |
---|---|
BOJ 그리디 문제 모음1/#11047동전0/#1931회의실배정/#11399ATM/#1541잃어버린 괄호/#1744수 묶기/#2875대회or인턴 (0) | 2020.03.23 |
리트코드(Leetcode)/Word_Ladder (0) | 2019.11.02 |
리트코드/leetcode/maxsubarray/부분최대합수열 (0) | 2019.10.05 |
leetcode/plusone (0) | 2019.10.05 |