PS(Java)/백준

[PS] 백준 11650번 좌표 정렬하기(Comparable과 Comparator)

UL :) 2022. 5. 18. 17:31

문제

 

11650번: 좌표 정렬하기

첫째 줄에 점의 개수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에는 i번점의 위치 xi와 yi가 주어진다. (-100,000 ≤ xi, yi ≤ 100,000) 좌표는 항상 정수이고, 위치가 같은 두 점은 없다.

www.acmicpc.net

 

풀이

참고한 풀이

Arrays.sort()는 2차원 배열의 정렬을 할 수 X →람다식을 사용하여 Arrays.sort() 확장

 

  • 일회성으로 함수를 써야할 경우 람다식으로 구현하는 것이 좋음
  • Comparator 의 경우 람다식으로 표현 할 수 있다

 

Arrays.sort()

  • java.util.Arrays의 Arrays.sort()
  • 기본 정렬조건 : 오름차순(Comparable인터페이스의 compareTo 메서드 기준)

 

Comparable과 Comparator의 차이점
둘 모두 인터페이스이다. 따라서 default나 static으로 선언된 메소드가 아닌 '추상메소드'를 구현해야한다.(자바 8 이후로 바뀜)

default로 선언된 메소드는 재정의(Override)를 할 수 있고, static은 재정의를 할 수 없다

 

기본타입은 부등호로 비교할 수 있지만, 얘네들은 '객체'를 비교할 수 있도록 해준다.

 

Comparable

  • java.lang --> import 할 필요X
  • Interface Comparable
  • 자기 자신과 매개변수 객체를 비교
  • 선언된 메서드 : int compareTo(T o)
    • 객체를 비교할 기준을 정의하는 부분. 자기 자신을 기준으로 상대방과의 차이 값을 비교하여 반환
    • which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.
    • 리턴 값
      • 자기자신 > 비교대상: 음수
      • 자기자신 < 비교대상: 양수 → 두 객체 위치를 바꾼다
      • 자기자신 == 비교대상: 0

 

예시 코드

import java.util.*;

class Brick implements Comparable<Brick>{
	public int s, h, w;
	
	Brick(int s, int h, int w){
		this.s = s;
		this.h = h;
		this.w = w;
	}
	
	@Override
	public int compareTo(Brick o) {
		return o.s - this.s; //내림차순
		//return this.s - o.s; //오름차순 default
	}
}

 

 

Comparator

  • java.util
  • Interface Comparator
  • 두 매개변수 객체를 비교
  • 선언된 메서드 많음, 실질적으로 구현해야 하는 메서드 : int compare(T o1, T o2)
    • which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.
    • 리턴 값
      • 자기자신 > 비교대상: 음수
      • 자기자신 < 비교대상: 양수 → 두 객체 위치를 바꾼다
      • 자기자신 == 비교대상: 0

 

TIP 🤍 두 값의 차를 반환해버리면 번거로운 조건식 없이 한방에 3개의 조건을 만족!!

 

주의 뺄셈 과정에서 자료형의 범위를 넘어버리는 경우가 발생할 수 있다. primitive 값에 대해 underflow/overflow 예외를 만약 확인하기 어렵다면 <, >, == 으로 대소비교를 해주는 것이 안전. 일반적으로 권장

 

Comparator에 대해 익명 클래스를 생성할 때. compare을 T[] 타입을 가진 매개변수를 람다식으로 바꾸어 쓸 수 있다

        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];
                }
            }
        });

위 코드를 람다식을 사용하여 아래 처럼.

          Arrays.sort(arr, (e1, e2) -> {
            if(e1[0] == e2[0]) {
                return e1[1] - e2[1];
            }
            else {
                return e1[0] - e2[0];
            }
        });

 

코드

import java.util.Arrays;
import java.util.Scanner;
import java.util.Comparator;

public class Main {

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        StringBuilder sb = new StringBuilder();

        int N = sc.nextInt();
        int arr[][] = new int[N][2];

        for(int i=0; i<N; i++) {
            arr[i][0] = sc.nextInt();
            arr[i][1] = sc.nextInt();
        }

        //x좌표를 오름차순 정렬
        //만약 x가 같으면 y가 작은순으로
        Arrays.sort(arr, new Comparator<int[]>() {

            @Override
            public int compare(int[] e1, int[] e2) {
                if(e1[0] == e2[0]) { //arr[][0] x값이 같으면
                    return e1[1] - e2[1]; //arr[][1] y를 비교!
                }
                else {
                    return e1[0] - e2[0]; //앞값이 크면 +, 작으면 -
                }
            }
        });


        Arrays.sort(arr, (e1, e2) -> {
            if(e1[0] == e2[0]) { //arr[][0] x값이 같으면
                return e1[1] - e2[1]; //arr[][1] y를 비교!
            }
            else {
                return e1[0] - e2[0]; //앞값이 크면 +, 작으면 -
            }
        });

        for(int i=0; i<N; i++) {
            sb.append(arr[i][0]+ " " + arr[i][1]).append("\n");
        }

        System.out.println(sb);
    }
}