코딩테스트
[level 1] 달리기 경주 - 178871
https://school.programmers.co.kr/learn/courses/30/lessons/178871
[level 1] 달리기 경주 - 178871 풀이코드
더보기
#include <string>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
// 값 조회시 속도를 위해 이름:순서, 순서:이름 으로 따로 맵을 생성했습니다.
map<int, string> rankMap;
map<string, int> nameMap;
vector<string> solution(vector<string> players, vector<string> callings) {
vector<string> answer;
int num = 1;
for (string i : players)
{
rankMap[num] = i;
nameMap[i] = num;
num++;
}
for (string i : callings)
{
int rank = nameMap[i];
int frontRank = rank - 1;
string temp = "";
temp += rankMap[frontRank];
rankMap[frontRank] = rankMap[rank];
rankMap[rank] = temp;
nameMap[temp] = rank;
nameMap[rankMap[frontRank]] = frontRank;
}
for (auto i : rankMap) answer.push_back(i.second);
return answer;
}
rBegin()과 end()→first의 차이점
과제를 진행하던 중에 multimap에서 마지막 값이 필요해서 사용하다가 발견하게 되었습니다.
// 점수와 학생 ID
multimap<int, int> scores;
scores.insert({70, 1});
scores.insert({80, 2});
scores.insert({90, 3});
다음 처럼 점수 목록이 있을 때 제가 필요한 건 최고 점수의 점수와 학생 ID, 그리고 최저 점수의 점수와 학생 ID를 구해야 하는 상황이었습니다.
int highScore, lowScore;
highScore = scores.begin()->first;
lowScore = scores.end()->first; // 자연스럽게 위에 begin()을 사용했으니 아래도 end()를 사용했다.
cout << "최고 점수 : " << highScore << "그리고 최저 점수 : " << lowScore << endl;
// 최고점수 : 90 그리고 최저 점수 : 3 -> ?
자연스럽게 begin()을 사용하고 end()를 사용했으나 결과 값은 완전히 달랐다.
그래서 어떤 게 잘못된 것일까 여러 가지 찾아보다가 알아보게 되었다.
end()는 컨테이너의 끝을 가리키지만, 실제 요소를 가리키지 않는다.
- end()는 마지막 요소의 다음을 가리키는 이터레이터
- 즉, 유효한 요소를 가리키는 게 아니라, “컨테이너의 범위를 벗어난 곳”을 가리키는 포인터이기 때문에 end()→first 같은 접근은 “미정의 동작(UB, Undefined Behavior)”이 된다.
- end()→first를 하면 에러가 나거나 예측할 수 없는 동작을 하게 된다. → 3이 아니라 다른 수가 나올 수도 있다.
rbegin()은 컨테이너의 마지막 요소를 가리킨다.
- rbegin()은 “마지막 요소를 가리키는 reverse iterator(역방향 이터레이터)
- rbegin()→first는 마지막 요소(역방향 첫 번째 요소)의 키 값을 의미
- 즉, rbegin()은 “마지막 요소”를 정확히 가리키는 반면, end()는 컨테이너의 끝을 벗어난 곳을 가리킨다.
결론
마지막 요소의 값을 가져올 때는
✔ rbegin() → 마지막 요소를 가리키므로 사용 가능
✔ end() → 마지막 요소의 다음을 가리키므로 사용 불가 (🚨UB 발생 가능)