페이지가 로드되지 않나요? 여기를 눌러보면 고쳐질 수도 있어요.
Placeholder

#8553

Tutorial : STL Sort 2 ( 정렬 기준 설정 ) 2s 1024MB

문제

앞선 문제에서는 sort 함수의 기본 사용법을 익혔다.

이젠 조금 더 어려운 정렬을 해볼 것이다.

파이썬의 경우 아래 두 가지 방법을 통해 좀 더 복잡한 정렬을 수행할 수 있다.

아래 두 코드 모두 (이름, 나이) 형태로 구성된 원소들을 가진 리스트를 나이를 우선적으로 정렬하며, 만약 나이가 같다면 이름이 사전순으로 더 앞서는 원소를 앞으로 정렬하는 코드다.

1. 두 원소 left와 right 비교하는 함수 사용하기

from functools import cmp_to_key

# left < right -> return 음수
# left == right -> return 0
# left > right -> return 양수 (정렬을 할 때 swap)
def comp(left, right):
    if  left[1] != right[1]:
        return -1 if left[1] < right[1] else 1
    if  left[0] != right[0]:
        return -1 if left[0] < right[0] else 1
    return 0

A = [ ("Bob", 15), ("Alice", 15), ("Ellie", 13) ]
A.sort(key = cmp_to_key(comp))

2. 원소 x에 대해 우선순위 정해주기

def priority(x):
    return ( x[1], x[0] )

A = [ ("Bob", 15), ("Alice", 15), ("Ellie", 13) ]
A.sort(key = priority)

아래 응용 문제를 풀어보며 감을 잡아보자.

<퀴즈>

배열의 정수들을 "일의 자리 숫자를 기준으로" 정렬해보자.

만약 일의 자리 숫자가 동일한 것들이 여러 개라면, 이들끼리는 "크기를 기준으로" 정렬한다.

즉, 정렬 기준의 1 순위"일의 자리 숫자"가 되고, 2 순위"크기" 가 되는 것이다.

예를 들면, 배열 A가 아래처럼 정렬되기를 원하는 것이다.

배열 A에서 오른쪽으로 갈수록,

일의 자리 숫자가 커지고, ( 1 순위 정렬 기준 )

일의 자리 숫자가 같은 것들끼리는 크기를 기준으로 정렬한 것이다. ( 2 순위 정렬 기준 )

아래 코드를 보면서 이해해보자.

#include <algorithm>
using namespace std;

// Left : 배열에서 왼쪽에 있는 수
// Right : 배열에서 오른쪽에 있는 수
bool comp ( int Left , int Right ){
    // 일의 자리 숫자가 다르다면 ?
    // 1 순위 정렬 기준 : 일의 자리 숫자로 비교
    if((Left % 10) != (Right % 10)){ 
        return (Left % 10) < (Right % 10);
    }
    // 일의 자리 숫자가 같았다면? 
    // 2 순위 정렬 기준 : 크기로 비교
    return Left < Right;
}

int main(){
    int i;
    int A[7] = {16, 28, 8, 6, 3, 26, 83};
    sort( A + 0 , A + 7 , comp); //  A = [ 3, 83, 6, 16, 26, 8, 28 ]
}

main 함수를 보면,

sort 함수 뒤에 인자가 하나 더 추가되어 있다. ( sort( A + 0 , A + 7 , comp ); )

뒤에 추가하는 bool 타입의 comp 함수는 두 수를 받아와서, 사용자가 설정한 정렬 기준을 바탕으로 비교하여 그 결과를 return 한다.

이를 직관적으로 이해하는 방법은 아래와 같다.

그림에서 보면, 배열에서 "오른쪽으로 갈수록 일의 자리 숫자가 커진다"는 것을 알 수 있다.

comp 함수에서 받아온 두 수를 LeftRight 로 이름을 지으면 이해하기 쉽다.

( 다른 변수 이름도 가능하다. 다만 이해를 돕기 위해 이렇게 이름을 지은 것이다. )

Left 는 배열에서 왼쪽에 있는 수, Right 는 배열에서 오른쪽에 있는 수다.

오른쪽으로 갈수록 일의 자리 숫자가 커져야 하므로, Left 보다 Right 의 일의 자리 숫자가 더 커야 한다.

그러므로 comp 함수 안에 이 코드가 적힌 것이다.

return (Left % 10) < (Right % 10);

여기에 이제 1 순위, 2 순위 정렬 기준만 넣어주면 된다.

1 순위 정렬 기준은 "일의 자리 숫자" 이다.

즉, Left 와 Right 의 일의 자리 숫자가 다르다면, 무조건 "일의 자리 숫자" 를 기준으로 둘을 비교하는 것이다.

만약 이 둘의 일의 자리 숫자가 같다면, 그 때 2 순위 정렬 기준인 "크기"를 기준으로 비교한다.

따라서 최종 comp 함수는 아래와 같다. 맨 처음 코드에 이를 설명하는 주석이 있으니 잘 읽어보자.

이 내용 만큼은 완벽하게 이해하고 다음으로 넘어가는 것이 중요하다.

몇 번 읽어봐도 이해가 가지 않는다면, 주변 선생님들께 적극적으로 질문하자.

bool comp ( int Left , int Right ){
    if((Left % 10) != (Right % 10)) return (Left % 10) < (Right % 10);
    return Left < Right;
}


<응용 문제>

N 개의 세 자리 정수들을 입력 받고, 이들을

1 순위 : 일의 자리 숫자

2 순위 : 십의 자리 숫자

3 순위 : 백의 자리 숫자

를 기준으로 오름차순 정렬해보자.


입력

첫 줄에 정수의 개수 N 을 입력 받는다. ( 1 ≤ N ≤ 100,000 )

두 번째 줄부터 각 줄에 걸쳐 N개의 정수들이 주어진다. ( 모든 정수는 세 자리 숫자임이 보장된다. )


출력

문제에서 요구하는 정렬 기준대로 이들을 정렬하여 출력하자.


예제 #1

7
123
837
219
119
323
228
991
991
123
323
837
228
119
219

예제 #2

8
263
463
533
536
266
466
336
333
333
533
263
463
336
536
266
466


출처

againalgo

로그인해야 코드를 작성할 수 있어요.