JAVA/백준

[백준] 11650번 좌표 정렬하기 JAVA

그건모르겠고 2024. 9. 11. 18:35
728x90

백준 : 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 메서드를 구현한다고 판단된다.


마무리

그렇게 어려운 문제는 아니라고 생각하지만, 람다식에 익숙하지 않으면 좀 어렵게 접근할 수 있을 거 같다.