[Python/javascript] 프로그래머스 : 체육복

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

체육복을 빌릴 때, 본인보다 한 번호 적은 학생에게 빌리는 것을 우선으로 한다고 가정하고 풀이했다

만일 reserve = [1,3] lost = [2,4]일 때 본인보다 1 큰 학생에게 빌리는 것을 우선한다면,

2번 학생은 3번에게, 4번 학생은 빌릴 수가 없게 되기 때문이다.

이상적인 형태는 2번 학생은 1번에게, 4번 학생은 2번에게 빌려 주는 것이기 때문에 본인보다 한 번호 작은 학생에게 빌리는 것을 우선한다고 생각하고 풀이를 했다.

 

추가적으로 고려할 것은, 여분을 잃을 것을 먼저 고려해야한다고 생각했다.

 

그래서 나는 여분 잃을 것을 먼저 고려(reserve와 lost 간) 후 왼쪽 학생에게 빌리는 로직을 설계했다.

 

Python

def solution(n, lost, reserve):
    answer = 0
    students = [False] * n
    for idx in range(len(reserve)):
        if reserve[idx] in lost: # 여분이 있는 학생이 체육복을 잃은 경우
            reserve.pop(idx)
            lost.remove(reserve[idx])
                        students[idx - 1] = True
    for idx in range(1,n+1):
        if idx in lost: # 체육복 잃어버린 경우
            if idx - 1 in reserve:
                students[idx - 1] = True
                reserve.remove(idx - 1)
                continue
            elif idx + 1 in reserve:
                students[idx - 1] = True
                reserve.remove(idx + 1)
                continue
        else: # 체육복 안 잃어버린 경우
            students[idx - 1] = True
    for res in students:
        if res == True:
            answer+= 1
    return answer

 

기존 풀이,,, 그러나 런타임 에러가 떴고, for loop 안에서 pop/remove를 하면 안 된다고 판단하여 다른 로직을 생각해야만 했다.

어떻게 remove랑 pop을 문제 없이 할 수 있을까? 내가 결국 해야하는 것은, pop과 remove가 아니라, lost와 reserve에 둘 다 들어있는 경우의 수를 한번 걸러주는 것이다.

 

def solution(n, lost, reserve):
    answer = 0
    students = [1] * n
    
    lost_set = list(set(lost) - set(reserve)) # 진짜로 잃어버린 경우만 남도록
    reserve_set = list(set(reserve) - set(lost)) # 진짜로 여분이 있는 경우만 남도록
    
    for idx in lost_set:
        students[idx - 1] -= 1
    for idx in reserve_set:
        students[idx - 1] += 1
    
    for idx in range(n):
        if students[idx] == 0:
            if n > 0 and students[idx - 1] >= 2: # 0번이 아니고, 왼쪽의 학생이 체육복을 2개 이상 가진 경우
                students[idx] += 1
                students[idx - 1] -= 1
            elif students[idx + 1] >= 2: # 그렇지 않으면 오른쪽만 봐주면 된다
                students[idx] += 1
                students[idx + 1] -= 1
    for cloth in students:
        if cloth:
            answer += 1
    return answer

set를 사용하면 pop, append 연산을 사용하지 않아도 될 것이라고 판단했다.

set를 사용하지 않고 새 배열을 만들거나 해도 될 것 같았으나 연산 시간의 문제로 append를 최대한 줄이고 싶었다. 그래서 set을 사용해 풀었다.

하지만 여전히 런타임 에러가 있었고,, 이를 극복하기 위해

Python Answer

def solution(n, lost, reserve):
    answer = 0
    students = [1] * n
    
    lost_set = list(set(lost) - set(reserve)) # 진짜로 잃어버린 경우만 남도록
    reserve_set = list(set(reserve) - set(lost)) # 진짜로 여분이 있는 경우만 남도록
    
    for idx in lost_set:
        students[idx - 1] -= 1
    for idx in reserve_set:
        students[idx - 1] += 1
    
    for idx in range(n):
        if students[idx] == 0:
            if idx > 0 and students[idx - 1] >= 2:
                students[idx] += 1
                students[idx - 1] -= 1
            elif idx < n - 1 and students[idx + 1] >= 2:
                students[idx] += 1
                students[idx + 1] -= 1

    for cloth in students:
        if cloth:
            answer += 1
    return answer

코드로 수정해주었다. 인덱스가 0이 아닌 경우 처리가 단순히 안 되었던 것.

 

Javascript Answer

function solution(n, initLost, initReserve) {
    var answer = 0;
    const lostSet = new Set(initLost);
    const reserveSet = new Set(initReserve);
    
    const lost = Array.from(new Set([...lostSet].filter(x => !reserveSet.has(x))));
    const reserve = Array.from(new Set([...reserveSet].filter(x => !lostSet.has(x))));
    
    let students = Array(n).fill(1)
    // 왼쪽에서부터 점검해주면 된다.
    for (idx = 0; idx < lost.length; idx++) {
        students[lost[idx] - 1] -= 1
    }
    for (idx = 0; idx < reserve.length; idx ++) {
        students[reserve[idx] - 1] += 1
    }
    
    for (idx = 0; idx < n; idx++) {
        if (students[idx] == 0) {
            if (idx > 0 && students[idx - 1] >= 2) {
                students[idx] += 1
                students[idx - 1] -= 1
            } else if (idx < n - 1 && students[idx + 1] >= 2) {
                students[idx] += 1
                students[idx + 1] -= 1
            }
        }
    }
    for (idx = 0; idx < n; idx++) {
        if (students[idx]) {
            answer += 1
        }
    }
    return answer;
}
TAGS.

Comments