영어 점수와 수학 점수의 평균 점수를 기준으로 학생들의 등수를 매기려고 합니다. 영어 점수와 수학 점수를 담은 2차원 정수 배열 score가 주어질 때, 영어 점수와 수학 점수의 평균을 기준으로 매긴 등수를 담은 배열을 return하도록 solution 함수를 완성해주세요.
진짜 완벽히 삽질하고 있었다 ! 3시간 동안 혼자 해결해 보고 싶어서 이리 바꾸고 저리 바꿨는데 도저히 답이 나오지 않았고, 더 꼬여만 가는 것 같아서 결국 다른 분들의 정답을 참고했다. 아래 코드는 정말 완벽히 삽질한 기록 중 하나.....
처음에는 이렇게 Map에 key와 value의 쌍으로 점수, 평균을 담은 다음 Comparator를 사용해 정렬 후, 값을 비교하며 setValue()로 Map의 value를 평균 -> 등수로 바꾸어 주려고 했는데, 생각해 보니 이렇게 풀면 공통 등수인 경우 제대로 비교해서 처리해줄 수가 없는 거다. 아당연함. 이전 인덱스 값이 등수로 바뀌었는데 어케 비교가 됨?ㅜㅜ
그래서 이후에는 rankMap이라는 평균과 학생 수를 함께 저장하는 객체를 하나 더 만들어 보기도 했는데, 역시 변수를 많이 쓰면 쓸수록 더 복잡해지기만 했다.
import java.util.*;
class Solution {
public int[] solution(int[][] score) {
int n = score.length;
int[] answer = new int[n];
Map<int[], Integer> sMap = new HashMap<>();
for (int[] s : score) {
int eng = s[0];
int math = s[1];
sMap.put(s, (eng + math) / 2);
}
List<Map.Entry<int[], Integer>> entryList = new ArrayList<>(sMap.entrySet());
Collections.sort(entryList, (e1, e2) -> e2.getValue().compareTo(e1.getValue()));
int rank = 1;
entryList.get(0).setValue(rank);
for (int i = 1; i < entryList.size(); i++) {
if (!entryList.get(i).getValue().equals(entryList.get(i - 1).getValue())) {
rank = i + 1;
}
entryList.get(i).setValue(rank);
}
for (int i = 0; i < score.length; i++) {
for (Map.Entry<int[], Integer> entry : entryList) {
if (Arrays.equals(score[i], entry.getKey())) {
answer[i] = entry.getValue();
break;
}
}
}
return answer;
}
}
이 정답에서 제일 열이 받았던 건(?) 굳이 평균을 구할 필요 없이 영어, 수학 점수의 합으로만 계산했어도 되었다는 것. 그리고 내가 풀면서도 너무 많은 변수를 사용한다 생각했는데, 깔끔한 코드를 보니 현타가 왔다.

아래 코드는 sort()와 Comparator.reverseOrder()를 통해 내림차순으로 점수들의 합을 정렬한 다음, 루프를 돌며 List에 담긴 합에 해당하는 인덱스를 indexOf()를 통해 반환하게 한다. 정렬을 하면 따로 등수를 생각해줄 필요 없이 0부터 시작하는 걸 +1 해서 1부터 시작하게끔 보정만 해주면 되는데 왜 그걸 생각 못했을까.
indexOf()의 특성상 중복된 값이 얼마나 있든 가장 앞에 있는 값의 인덱스를 반환할 테고, 그렇게 중복된 값들을 인덱스에 +1해 모두 같은 등수로 처리하고 나면 그 다음 값은 중복된 값의 개수 만큼을 자연스럽게 건너 뛰고 자신의 인덱스에 맞는 등수를 할당받게 되는 것이다.
import java.util.*;
class Solution {
public int[] solution(int[][] score) {
List<Integer> scoreList = new ArrayList<>();
for(int[] s : score){
scoreList.add(s[0] + s[1]);
}
scoreList.sort(Comparator.reverseOrder());
int[] answer = new int[score.length];
for(int i=0; i<score.length; i++){
answer[i] = scoreList.indexOf(score[i][0] + score[i][1])+1;
}
return answer;
}
}
각 메서드의 특성을 너무 어렴풋이 알고 있거나 쓰는 것만 써서 이런 문제가 발생하는 것 같다는 생각을 했다. 그리고 문제에 주어졌다고 해도 제한사항, 필수 제약 조건이 아닌 이상 계산을 간소화하는 방향을 가장 먼저 구상해 봐야겠다는 생각도 했다. 무엇보다 하다가 안 되면 더 이상 미련 갖지 말고 초기화 후에 완전히 새로운 접근 방식을 찾아 보는 것이 도움이 되겠다는 걸 느낀 문제였다.
