정수 n을 기준으로 n과 가까운 수부터 정렬하려고 합니다. 이때 n으로부터의 거리가 같다면 더 큰 수를 앞에 오도록 배치합니다. 정수가 담긴 배열 numlist와 정수 n이 주어질 때 numlist의 원소를 n으로부터 가까운 순서대로 정렬한 배열을 return하도록 solution 함수를 완성해주세요.
numlist가 중복된 원소를 갖지 않는다는 조건에서 착안해 해당 원소를 key로, n과의 거리를 value로 하여 Map 객체에 저장해야겠다고 생각했다.
루프를 돌며 numlist의 원소를 받아와 HashMap에 put() 할 때, key는 원소로 value는 Math.abs()를 사용해 구한 거리, 즉 절댓값으로 데이터가 저장되게 했다.
다음으로는 HashMap에 저장된 value를 오름차순으로 정렬해야 했다. 처음에는 map의 Entry를 List로 변환한 뒤, Map.Entry에 있는 comparingByValue() 메서드를 사용해 값을 기준으로 정렬을 하려고 했다. 그런데 고려해야 하는 조건 중 '같은 값이라면 = 거리가 같다면 더 큰 수를 우선한다'는 조건을 충족시키기가 어려웠다.
그래서 더 복잡한 정렬 조건을 활용할 수 있는 comparator 인터페이스를 사용해보기로 했다. List 타입으로 변환된 Map을 Collections.sort()를 활용해 정렬하되, comparator를 두 번째 인자로 넣고 compare() 메서드를 오버라이딩하여 조건 2가지를 추가했다.
compare(): 두 객체가 같은지 어느 하나가 더 큰지 나타내는 값을 반환해야 함
- 음수: 첫 번째 객체가 두 번째 객체보다 작음을 나타냅니다.
- 0: 두 객체가 같음을 나타냅니다.
- 양수: 첫 번째 객체가 두 번째 객체보다 큼을 나타냅니다.
먼저 비교해야 하는 Map entry의 값 2개를 getValue()를 통해 변수에 저장하고, 만약 그 값이 같다면 return e2.getKey() - e1.getKey(); 두 숫자를 비교하여 더 큰 수가 앞에 오도록 하고, 거리가 다르다면 return dist1 - dist2; 두 거리의 차이를 반환하여 더 작은 거리가 앞에 오도록 한다.
그렇게 정렬이 완료된 entryList의 사이즈 만큼 반환 타입인 정수형 배열의 크기를 할당한 뒤, 루프를 돌며 entryList.get(i).getKey()로 List에 담긴 entry에서 key를 꺼내어 answer[i]에 저장해 준다.
import java.util.*;
class Solution {
public int[] solution(int[] numlist, int n) {
Map<Integer,Integer> numMap = new HashMap<>();
for(int num : numlist){
numMap.put(num, Math.abs(n - num));
}
List<Map.Entry<Integer,Integer>> entryList = new LinkedList<>(numMap.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) {
int dist1 = e1.getValue();
int dist2 = e2.getValue();
if (dist1 == dist2) return e2.getKey() - e1.getKey();
return dist1 - dist2;
}
});
int[] answer = new int[entryList.size()];
for(int i=0; i<entryList.size(); i++){
answer[i] = entryList.get(i).getKey();
}
return answer;
}
}
