[Programmers] 6주차

퍼롱's·2021년 9월 6일
0

🍒Programmers🍒

목록 보기
7/11
post-thumbnail

출처: 프로그래머스 코딩테스트 연습
https://programmers.co.kr/learn/courses/30/lessons/85002

파이썬 정렬(sort, sorted)

  • list.sort() : 리스트를 제자리에서 수정하고 None을 반환하는 메서드, 원래 목록이 필요하지 않을 때 유용
  • sorted() : 리스트 뿐 아니라 모든 이터러블을 받아들여 새롭게 정렬된 리스트 반환하는 내장함수
  • 기본적으로 오름차순 정렬이며, reverse=True 속성을 넣어주면 내림차순 정렬이 가능
  • 정렬 안정성 : 여러 레코드가 같은 키를 가질 때, 원래의 순서 유지

출처 : Sorting HOW TO - Python 3.9.7 documentation

📝 풀이(python3)

def solution(weights, head2head):
    wins = []
    for i in head2head:
        if i.count('W')+i.count('L') != 0: # 싸운 적이 있으면 승률 = 이긴 횟수/싸운 횟수
            wins.append(i.count('W')/(i.count('W')+i.count('L')))
        else: # 싸운 적이 없으면 승률 = 0
            wins.append(0)
    heavy_win = [0] * len(weights)
    for i, h in enumerate(head2head):
        for j, d in enumerate(h):
            if d == 'W' and weights[i] < weights[j]: # 자신보다 무거운 무게의 복서를 이긴 경우
                heavy_win[i] += 1 
    player = []
    for i, w in enumerate(wins): # 번호, 승률, 무거운 복서 이긴 횟수, 몸무게 순으로 정렬
        player.append([i+1, w, heavy_win[i], weights[i]])

    answer = []
    # 우선순위 순서 반대로 정렬, 이미 번호 순서대로 오름차순 정렬 되어있으므로 몸무게, 무거운 복서 이긴 횟수, 승률 차례로 내림차순 정렬
    player.sort(key=lambda x:x[3], reverse=True) # 몸무게 순으로 내림차순 정렬
    player.sort(key=lambda x:x[2], reverse=True) # 무거운 복서 이긴 횟수 순으로 내림차순 정렬
    player.sort(key=lambda x:x[1], reverse=True) # 승률 순으로 내림차순 정렬
    for p in player:
        answer.append(p[0])
    return answer
정확성  테스트
테스트 1 〉	통과 (0.02ms, 10.2MB)
테스트 2 〉	통과 (0.02ms, 10.3MB)
테스트 3 〉	통과 (0.02ms, 10.3MB)
테스트 4 〉	통과 (0.02ms, 10.3MB)
테스트 5 〉	통과 (0.02ms, 10.2MB)
테스트 6 〉	통과 (45.60ms, 11MB)
테스트 7 〉	통과 (57.25ms, 11.5MB)
테스트 8 〉	통과 (59.92ms, 11.7MB)
테스트 9 〉	통과 (28.90ms, 10.6MB)
테스트 10 〉	통과 (13.89ms, 10.5MB)
테스트 11 〉	통과 (68.62ms, 11.5MB)
테스트 12 〉	통과 (22.26ms, 10.9MB)

채점 결과
정확성: 100.0
합계: 100.0 / 100.0

리스트를 우선순위로 정렬하는 법 때문에 꽤나 오랫동안 고민했지만 파이썬의 정렬 속성을 제대로 알지 못해서 별로인 코드를 짰다고 생각했다

우선 나의 풀이는 파이썬은 정렬 안정성이 있기에 우선순위의 반대로 정렬을 해준 것이다

다른 사람의 풀이를 보니 파이썬의 sort는 동률이면 다음 요소를 보고 정렬을 해준다고 한다

for문을 좀 덜 쓰고 위와 같은 속성을 이용해서 다시 코드를 짜보았다

  1. 승률 내림차순 정렬
  2. 자신보다 무거운 몸무게를 가진 복서를 이긴 횟수 내림차순 정렬
  3. 몸무게 내림차순 정렬
  4. 복서 번호 오름차순 정렬

복서 번호만 오름차순 정렬이므로 번호에 음수를 붙여 음수로 내림차순 정렬을 시켜준다

따라서 player자체를 내림차순 정렬 시켜주면 우선순위에 맞게 정렬이 되고 각 리스트의 끝 값은 번호에 음수를 붙여준 형태이니 다시 원래 번호를 answer에 넣어 답으로 return한다

def solution(weights, head2head):
    player = [[0,0,0,0] for _ in range(len(weights))] # 승률, 더 큰 무게 이긴 횟수, 몸무게, -(번호) 순으로(우선순위를 판단하는 순서) 정렬
    for i, h in enumerate(head2head):
        if h.count('W')+h.count('L') != 0: # 싸운 적 있는 경우, 승률 = 이긴 횟수/싸운 횟수
            player[i][0] = h.count('W')/(h.count('W')+h.count('L'))
        else: # 싸운 전적이 없는 경우 승률 = 0
            player[i][0] = 0 
        for j, d in enumerate(h): # 자신 무게보다 더 큰 무게의 복서를 이긴 횟수
            if d == 'W' and weights[i] < weights[j]:
                player[i][1] += 1
        player[i][2] = weights[i] # 본인의 몸무게
        player[i][3] = -(i+1) # 본인 번호의 음수
    
    player.sort(reverse=True) # 전체 내림차순 정렬
    answer = []
    for p in player:
        answer.append(-p[-1]) # 원래 번호를 answer에 append
    return answer
정확성  테스트
테스트 1 〉	통과 (0.02ms, 10.3MB)
테스트 2 〉	통과 (0.02ms, 10.4MB)
테스트 3 〉	통과 (0.02ms, 10.3MB)
테스트 4 〉	통과 (0.03ms, 10.3MB)
테스트 5 〉	통과 (0.03ms, 10.2MB)
테스트 6 〉	통과 (48.71ms, 10.9MB)
테스트 7 〉	통과 (64.85ms, 11.4MB)
테스트 8 〉	통과 (63.18ms, 11.8MB)
테스트 9 〉	통과 (38.12ms, 10.6MB)
테스트 10 〉	통과 (21.29ms, 10.7MB)
테스트 11 〉	통과 (110.83ms, 11.4MB)
테스트 12 〉	통과 (22.32ms, 10.8MB)

채점 결과
정확성: 100.0
합계: 100.0 / 100.0

한 번에 player리스트를 만들어서 한 번만 정렬시키는 것이라 더 효율성 면에서 좋을 것이라 생각했는데 의외로 통과한 시간이 내가 짰던 코드보다 좀 더 길게 나와서 당황스럽다

뭐 때문이지... for문 자체를 짧게 여러번 돌리는 게 더 나은 것인가....? 공부해봐야겠다

profile
유지경성

0개의 댓글