파이썬 알고리즘

Seokhyun Yoon·2023년 9월 18일

해시 카테고리의 베스트 앨범 Lv3를 못 풀었다.
그래서 이해를 위한 정리를 남긴다.

문제

입출력 예제
genres plays return 순으로 아래 입출력이 주어진다.
["classic", "pop", "classic", "classic", "pop"]
,[500, 600, 150, 800, 2500]
,[4, 1, 3, 0]

문제의 의도는 입력으로 주어지는 두 리스트와 출력해야하는 리스트 하나를 합쳐서 딕셔너리와 리스트의 자료구조를 잘 이해하고 있냐는 의중같다.

처음 문제를 풀 때에는 딕셔너리 내부에 리스트를 삽입한다는 생각자체를 못했다.

카테고리 별 plays의 합을 구하고 이를 내림차순으로 정렬한 딕셔너리를 만든 것 까지는 했으나, 문제는 그 중 plays가 큰 순서대로 내림차순을 해

값이 큰 순서대로 2개를 꺼낸다음 idx를 구해서 answer 리스트에 append 한다는 부분이 해결되지 않았다.

이유는 내림차순을 하였을때 그게 어떤 카테고리이며, 어떤 idx였는지 자료의 정보가 zip되지 않았기 때문.

다른 사람의 풀이

프로그래머스 다른 사람의 풀이에 가장 맨 위에 있는 코드다.

def solution(genres, plays):
    answer = []
    d = {e:[] for e in set(genres)}
    print('d', d)
    for e in zip(genres, plays, range(len(plays))):
        
        d[e[0]].append([e[1] , e[2]])
    genreSort =sorted(list(d.keys()), key= lambda x: sum( map(lambda y: y[0],d[x])), reverse = True)
    print(d, genreSort)
    for g in genreSort:
        temp = [e[1] for e in sorted(d[g],key= lambda x: (x[0], -x[1]), reverse = True)]
        answer += temp[:min(len(temp),2)]
    return answer

알고 넘어가야 할 개념

  • dictionary
  • list
  • zip
  • sorted
  • Dictionary Comprehension

set을 이용하여 카테고리의 중복을 제거한 후 key인 e를 Dictionary Comprehension를 이용하여 key: [ ] 형태로 만듦

ex) "classic" : [] 같은 형태

zip을 이용해 매개변수에 전달된 여러 리스트들을 하나로 합쳐준다.

zip() 함수는 여러 시퀀스(리스트, 튜플 등)를 동시에 이어붙여 하나의 시퀀스로 만들어주는 함수입니다.

ex) 
genres = ["classic", "pop", "rock"]
plays = [500, 600, 700]
indices = [0, 1, 2]

for e in zip(genres, plays, indices):
    print(e)
실행결과  >
('classic', 500, 0)
('pop', 600, 1)
('rock', 700, 2)

이런식으로 매개변수에 전달된 리스트들이 zip에 의해 하나로 합쳐진다.

genreSort =sorted(list(d.keys()), key= lambda x: sum( map(lambda y: y[0],d[x])), reverse = True)

이 부분은 각 키 x에 대해 앞서 사용했던 d 딕셔너리의 d[x] 즉 x 키에 해당하는 value의 결과물 y의 0번째 idx인 plays를 추출.

그리고 추출한 것을 map을 이용해서 각 요소들을 sum 해줌(누적)

이후 key option은 비교 연산 대상.
sorted(list(d.keys()), reverse = True)내림차순으로 정렬한 다음 d.keys()를 list로 반환한 문법이다.

for g in genreSort:
temp = [e[1] for e in sorted(d[g],key= lambda x: (x[0], -x[1]), reverse = True)]

이것은 정렬된 genre 리스트 ['pop', 'classic'] 의 모든 요소들을 g를 이용해 반복할거임

이때 정렬 대상인 d[g]는 d 딕셔너리의 key === g then value
x[0]는 d[g][0]을 생각하면 된다.

ex) {'classic': [[500, 0]} classic이 d[g]다. 그리고 그것의 value [0]은 500이다
즉 500으로 먼저 오름차순 정렬을 하고 부가조건인 -x[1]은 오름차순 정렬중

중복되는 plays가 있을 경우 idx에 -를 입혀서 내림차순 정렬시킨다
(이렇게 하게되면 처음 매개변수로 주어진 genres에 삽입된 순서대로 정렬).

아무튼 최종적으로 다시 내림차순 정렬한다음. key e를 e[1]형태로 반환한다.

이 결과물인

  • temp는 [4, 1][3, 0, 2] 이렇게 나옴
  • 이제 2개씩만 수록하면 4,1,3,0 답이 나온다.
  • 그래서 무조건 2개씩 수록할 수 있도록 temp에서 맨앞 2개 가져 갈 수 있도록 슬라이스 쳐준다.
profile
Web과 Cloud에 관심이 있습니다.

0개의 댓글