python/알고리즘 문제풀이

[프로그래머스 | 파이썬3] 체육복_ set, pop 사용

빛날희- 2021. 5. 13. 16:30

https://programmers.co.kr/learn/courses/30/lessons/42862

 

코딩테스트 연습 - 체육복

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번

programmers.co.kr

 

체육복을 도난당한 경우, 즉 같은 번호가 reserve에도 있고 lost에도 있는 경우까지 고려하는 것이 까다로웠던 문제였다. 나는 차집합 개념과 pop함수를 활용하여 문제를 풀었다. 

 


1. 첫번째 시도: 오답

 

처음엔 위의 경우를 고려하지 않고 작성하였다. 이렇게 코드를 작성할 경우 test에서 3개의 문항이 오답인 것으로 나온다. 

pop함수를 사용하여 lost의 학생번호의 -1 번호 또는 +1 번호가 reserve에 있으면 reserve에서 해당 번호를 제거해주는 방식(한번 체육복을 빌려준 학생들이 또 체육복을 빌려주지 못하도록 제거해야 함)으로 작성했다. 

# reserve에 있는 학생이 하나를 도난당할 수 있는 경우 고려안함
def solution (n, lost, reserve):
    result= len(reserve) 
    for i in lost:
        try:
            reserve.pop(reserve.index(i-1))
        except: 
            try: reserve.pop(reserve.index(i+1))
            except: continue
    result += (result - len(reserve)) + (n-result-len(lost))
    return result

 

 

2. 두번째 시도: 런타임 에러

 

lost와 reserve에 동시에 존재하는 경우를 고려해주기 위해 공통으로 존재하는 요소를 따로 빼 준 for문을 활용해 두 배열에서 공통요소를 빼주고자 하였다. 또한 공통 요소는 체육복을 빌려줄 수 없는 상태이기에 reserve에서 미리 해당 요소를 빼주었다. 

하지만 for문을 2번 사용해서인지 런타임에러가 떴다. 알고리즘 문제 풀이 시 for문의 활용은 최소한으로 해야겠다. 

# 런타임 에러
def solution (n, lost, reserve):
    dup= list(set(lost) & set(reserve))
    if dup: 
        for i in dup:
            reserve.pop(i)
            lost.pop(i)
    total= len(set(lost+reserve))
    result= len(reserve) 
    for i in lost:
        try:
            reserve.pop(reserve.index(i-1))
        except: 
            try: reserve.pop(reserve.index(i+1))
            except: continue
    result += (result - len(reserve)) + (n-total)
    return result

 

 

3. 마지막 시도: 통과

 

for문을 사용하지 않고 공통요소를 빼는 방법으로 차집합을 생각하였다. 차집합을 통해 공통요소가 제거된 두 배열을 다시 만들어 준 후 result를 계산하는 방식도 조금 바꾸었다. 

마지막에서 result를 한번에 계산해주는 방식이 아니라 set_reserve에서 요소가 하나씩 제거될 때 (여분의 체육복을 lost학생들에게 빌려줄 때 == 체육 수업에 참가할 수 있는 학생들이 한명씩 늘어날 때) result에 1씩 더하는 방식으로 바꾸었다. 

def solution (n, lost, reserve):
    set_lost= list(set(lost)-set(reserve))
    set_reserve= list(set(reserve)-set(lost))
    
    result= len(set_reserve) + (n - len(set_lost+set_reserve))
    
    for i in set_lost:
        try:
            set_reserve.pop(set_reserve.index(i-1))
            result += 1
        except: 
            try: 
                set_reserve.pop(set_reserve.index(i+1))
                result += 1
            except: continue
    return result