[백준] 11650번 좌표 정렬하기 JAVA
백준 : https://www.acmicpc.net/problem/11650
백준 알고리즘을 풀면서 이해가 되지 않았던 내용을 글로 남기고자 한다.
상기 좌표 정렬하기 문제에서 2차배열과 Array.sort() 사용해야 한다고 생각했지만, 조금 더 쉽게 구현하고자 생각하면서 찾은 내용이 람다식이었다..
해당 방법은 아래 출처에서 참고했다. 이해하기 쉽게 잘 설명 해주었다.
https://st-lab.tistory.com/110
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[][] arr = new int[N][2];
StringTokenizer st;
for(int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
arr[i][0] = Integer.parseInt(st.nextToken()); // x 좌표
arr[i][1] = Integer.parseInt(st.nextToken()); // y 좌표
}
Arrays.sort(arr, new Comparator<int[]>() {
@Override
public int compare(int[] e1, int[] e2) {
if(e1[0] == e2[0]) { // 첫번째 원소가 같다면 두 번째 원소끼리 비교
return e1[1] - e2[1];
}
else {
return e1[0] - e2[0];
}
}
});
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i< N ; i++) {
sb.append(arr[i][0] + " " + arr[i][1]).append('\n');
}
System.out.println(sb);
}
}
Array.sort() 자바 API 문서를 보면 sort 메소드는 두 가지 인자값을 받을 수 있다.
첫 번째는 제네릭 타입 객체배열( T[] ) 이다, 어떤 타입이든 상관없이 배열의 형태로 받을 수 있다는 의미다.
위의 경우는 2차원 배열 넘겨 줄 거니 T 는 int[] 타입이 될 것이다.
두 번째로는 Comparator<? super T> c 이다. <? super T> 는 상속관계에 있는 타입만 자료형으로 받겠다는 의미다.
정렬할때 기준이 되고 판단할 수 있는 인자값이다.
T 타입이 자식클래스가 되고, T의 상속관계에 있는 타입까지만 허용하겠다는 의미다. 위에서는 상속관계에 있는 데이터를 정렬하지 않기 때문에 <T> 와 같다고 봐도 된다.
Comparator 의 경우 인터페이스로 우리가 구현해야 되는 메소드는 compare(T o1, T o2) 이다.
arr[N][2] 배열이 있고, 두 좌표를 비교했을때, arr[i][0]과 arr[i+1][0] 정렬하면서 두 값이 같으면 arr[i][1] 과 arr[i+1][1] 을 비교할 것이다.
비교 결과에 따라 양수, 음수, 0을 반환하여 정렬 순서를 지정한다.
하지만, 좀더 쉽고, 가독성을 높이기 위해 익명 함수인 람다식을 쓸 수 있다.
Arrays.sort(arr, (e1, e2) -> {
if(e1[0] == e2[0]) {
return e1[1] - e2[1];
}
else {
return e1[0] - e2[0];
}
});
따로 메소드를 구현하지 않고 위와 같이 쓸 수 있다.
compare 메서드가 명시적으로 정의되지 않아도 컴파일러가 람다 표현식이 어떤 인터페이스의 추상 메서드로 구현한다 는 것을 유추할 수 있음
여기서 Comparator 인터페이스도 함수형 인터페이스 중 하나이며, 유일한 추상 메서드는 compare 메서드입니다.
람다 표현식 (e1, e2) -> { ... }는 매개변수 두 개를 받는 함수를 나타내는데, 이는 Comparator 인터페이스의 compare 메서드의 시그니처와 일치하다.
컴파일러는 람다 표현식의 형태와 Arrays.sort 메서드의 요구 사항을 비교하여, 이 람다 표현식이 Comparator 인터페이스의 compare 메서드를 구현한다고 판단된다.
마무리
그렇게 어려운 문제는 아니라고 생각하지만, 람다식에 익숙하지 않으면 좀 어렵게 접근할 수 있을 거 같다.