출처: https://school.programmers.co.kr/learn/courses/30/lessons/120835?language=python3
문제 설명
외과의사 머쓱이는 응급실에 온 환자의 응급도를 기준으로 진료 순서를 정하려고 합니다. 정수 배열 emergency가 매개변수로 주어질 때 응급도가 높은 순서대로 진료 순서를 정한 배열을 return하도록 solution 함수를 완성해주세요.
제한사항
중복된 원소는 없습니다.
1 ≤ emergency의 길이 ≤ 10
1 ≤ emergency의 원소 ≤ 100
입출력 예
emergency result
[3, 76, 24][3, 1, 2]
[1, 2, 3, 4, 5, 6, 7][7, 6, 5, 4, 3, 2, 1]
[30, 10, 23, 6, 100][2, 4, 3, 5, 1]
입출력 예 설명
입출력 예 #1
emergency가 [3, 76, 24]이므로 응급도의 크기 순서대로 번호를 매긴 [3, 1, 2]를 return합니다.
입출력 예 #2
emergency가 [1, 2, 3, 4, 5, 6, 7]이므로 응급도의 크기 순서대로 번호를 매긴 [7, 6, 5, 4, 3, 2, 1]를 return합니다.
입출력 예 #3
emergency가 [30, 10, 23, 6, 100]이므로 응급도의 크기 순서대로 번호를 매긴 [2, 4, 3, 5, 1]를 return합니다.
내가 작성한 코드문
def solution(emergency):
answer = []
# 딕셔너리 활용
dic = {}
for i in range(len(emergency)): # 이렇게 하면 인덱스와 원소값 이런식으로 묶인다.
dic[i + 1] = emergency[i]
print(dic)
# 여기서 밸류값끼리 큰 순서대로 정렬 한다.
sorted_dic = sorted(dic.items(), key= lambda item:item[1], reverse=True)
print(sorted_dic)
print(sorted_dic.values())
# 키값도 한번 바꿔준다 1, 2, 3
# for i in range(len(emergnecy)):
# sorted_dic.values()
# 그리고 키 값을 answer 리스트에 저장한다.
idx = 0
for i in range(len(emergency)):
answer.append(sorted_dic[i])
idx += 1
return answer
트러블 슈팅
내 생각엔 딕셔너리를 활용하여 키값과 밸류값을 활용하여
리스트를 딕셔너리에 저장후 밸류값끼리 큰순서대로 정렬하고,
그 밸류값 순서대로 answer 리스트에 저장하는 방식을 생각했다.
아예 틀린건 아니지만, 응급도에 따른 순위 매기기를 달성하기 어렵거나 불필요한 복잡성이 발생한다.
딕셔너리를 값(Value) 기준으로 정렬하는 순간, 정렬된 결과인 sorted_dic은 값의 크기 순서((2: 70), (1: 30), (3: 20))만 알려줄 뿐, 최종적으로 "원래 1번 자리에는 순위 2를, 원래 2번 자리에는 순위 1을 넣어야 한다"는 정보를 직접적으로 알려주지 않는다.
딕셔너리는 순서를 보장하지 않기 때문에, 정렬하려면 항상 dic.items()를 통해 리스트 형태의 튜플로 변환해야 한다.
def solution(emergency):
# 1. 내림차순 정렬 (순위 매길 기준 준비)
sorted_emergency = sorted(emergency, reverse=True)
# 2. {응급도 값: 순위} 딕셔너리 생성
rank_map = {}
# enumerate를 사용하여 인덱스(0, 1, 2...)를 순위(1, 2, 3...)로 활용
for index, value in enumerate(sorted_emergency):
rank_map[value] = index + 1 # 순위는 1부터 시작
# 3. 원본 리스트를 순회하며 순위로 변환
answer = []
for val in emergency:
# 딕셔너리에서 해당 값의 순위를 찾아서 리스트에 추가
answer.append(rank_map[val])
return answer
# 예시: emergency = [3, 76, 24]
# 1. sorted_emergency = [76, 24, 3]
# 2. rank_map = {76: 1, 24: 2, 3: 3}
# 3. answer = [rank_map[3], rank_map[76], rank_map[24]] = [3, 1, 2]
인덱스와 밸류값을 반환하기 위해 enumerate를 사용 한다는 점, 딕셔너리의 반복문 돌기가 아직 생소하다.
다른 사람의 풀이
def solution(emergency):
return [sorted(emergency, reverse=True).index(e) + 1 for e in emergency]
sorted(emergency, reverse=True) 또는 e 변수가 응급도를 내림차순(큰 값부터)으로 정렬한 리스트를 만든다.
원본 리스트 emergency의 각 요소(e 또는 i)를 순서대로 가져온다.
정렬된 리스트 e에서 현재 값의 인덱스를 찾는다.
76의 인덱스는 0 (1등)
24의 인덱스는 1 (2등)
3의 인덱스는 2 (3등)
def solution(emergency):
answer = []
emer_ls = {e: i + 1 for i, e in enumerate(sorted(emergency)[::-1])}
for e in emergency:
answer.append(emer_ls[e])
return answer
정렬 및 뒤집기: sorted(emergency)[::-1]은 emergency 리스트를 내림차순(큰 값부터)으로 정렬
순위 딕셔너리 생성 (핵심):
enumerate를 사용하여 순위(인덱스 i)와 응급도 값(e)을 동시에 얻는다.
emer_ls = {76: 1, 24: 2, 3: 3} 형태의 순위 매핑 딕셔너리를 생성한다.
index()를 반복 호출하는 것보다 훨씬 빠르다. 딕셔너리 조회는 평균적으로 시간 복잡도를 가지기 때문에 가장 효율적인 풀이다.
def solution(emergency):
arr = [] # 최종 순위를 저장할 리스트
# 1. 첫 번째 반복문: 순위를 매길 기준 요소 (i)를 하나씩 선택
for i in emergency:
idx = 1 # 순위는 기본적으로 1등으로 시작
# 2. 두 번째 반복문: 기준 요소 i를 리스트의 모든 요소 (j)와 비교
for j in emergency:
# 3. 비교: 기준 요소 i보다 더 큰 값 j가 있다면
if i < j:
idx += 1 # 순위(idx)를 1 증가시킵니다 (더 큰 값이 있다는 것은 최소한 그만큼 순위가 밀린다는 의미)
# 4. 순위 확정: i의 순위가 확정되면 최종 리스트에 추가
arr.append(idx)
return arr