본문으로 바로가기

백준 10825 국영수 (파이썬 python)

 

10825번: 국영수

첫째 줄에 도현이네 반의 학생의 수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 한 줄에 하나씩 각 학생의 이름, 국어, 영어, 수학 점수가 공백으로 구분해 주어진다. 점수는 1보다 크거나 같고, 1

www.acmicpc.net

문제 풀이 및 접근

  • 처음에는 국어 → 영어 →수학 →이름과 같이 맨 윗단 부터 아랫단까지 정렬하는 방식을 생각했었습니다. 국어 점수가 같은 것끼리 한 단위로 정하고 그 단위 내에서 영어 점수 정렬하고 정렬한 것 중에서 영어 점수가 같은 것끼리 또 단위로 묶는 방식을 반복하며 이름까지 정렬하는 방식으로 생각했었습니다. 이렇게 하면 단위가 굉장히 많아지고 이러한 단위를 나누는 idx 정하는 방법을 어떻게 정하는지, 나누는건 재귀로 해야하는지 자꾸 애매했습니다.
  • 그러다가 위의 반대로 이름→수학→ 영어→국어같이 밑단 부터 위 순서로 정렬하면 간단하게 해결되는 것을 알 수 있었습니다.
  • 입력값을 내장함수 input으로 받아오는 것도 해보고 sys.stdin.readline으로 받아보았습니다. 둘 다 통과되었지만 시간 차이가 상당했습니다. 앞으로 입력 값이 많으면 sys library 사용을 잊지 말아야겠습니다.

입력을 어떻게 받는지에 따라 10배 가까운 시간 차이 발생.

 

Code

import sys
input = sys.stdin.readline
n = int(input())
student = []
for i in range(n):
    chunk = input().split()
    student.append( [ chunk[0] , int(chunk[1]),int(chunk[2]),int(chunk[3]) ] )

student.sort(key = lambda x:x[0])
student.sort(key = lambda x:x[3], reverse = True)
student.sort(key = lambda x:x[2])
student.sort(key = lambda x:x[1], reverse = True)

for i in student:
    print(i[0])

 

추가1 - 파이썬에서 튜플을 원소로 하는 리스트

파이썬에서 튜플을 원소로 하는 리스트가 있을 때, 그 리스트를 정렬하면 기본적으로 각 튜플을 구성하는 원소의 순서에 맞게 정렬이 됩니다. 예를 들어 리스트 안의 한 튜플이 세 개의 원소로 구성되어 있다면 리스트를 정렬할 때 모든 원소가 첫 번째 원소의 순서에 맞게 정렬되고, 첫 번째 원소의 값이 같다면 두 번째 원소를 기준으로, 두 번째 원소의 값도 같아면 세 번째 원소 기준으로 정렬됩니다.

test = [  (3,1,5) , (2,2,4) , (2,1,5) , (2,1,2)  ]
test.sort()

print(test)
# [ (2,1,2) , (2,1,5) , (2,2,4) , (3,1,5) ]

 

추가2 - sort() key method 이용해서 짧은 코드로 만들기

import sys
input_ = sys.stdin.readline
n = int(input_())
student = []
for i in range(n):
    student.append( input_().split() )

student.sort(key = lambda x: (-int(x[0]), int(x[2]), -int(x[3]),x[0]   ))

for i in student:
    print(i[0])
  • key argument 에 lambda 함수를 이용하면 여러 가지 sorting 조건을 우선 순위에 맞춰 한 번에 지정할 수 있었습니다. 
  • sort() 에서 default는 오름 차순이지만, - 를 붙여 내림 차순으로 표현하는 것이 인상적이였습니다. 
  • 이렇게 하면 코드가 짧아지지만 위의 방법에 비해서 메모리를 약 두 배 더 쓰고 시간도 15% 정도 더 소모되었습니다.