본문 바로가기
ALGORITHM/프로그래머스 With JS

[프로그래머스] 체육복 / Javascript

by LAY CODER 2021. 4. 28.

문제

 

코딩테스트 연습 - 체육복

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

programmers.co.kr


 

TRY

function solution(n, lost, reserve) {

    var answer = 0;

    // 학생 수 만큼 배열의 가지고 있는 유니폼 수를 1로 초기화
    let hasUniform = new Array(n).fill(1);

    // 잃어버린 학생은 -1 을 해줌
    for (let i = 0; i < lost.length; i++) {
        hasUniform[lost[i] - 1]--;
    }

    // 여벌이 있으면 +1 을 해줌
    for (let i = 0; i < reserve.length; i++) {
        hasUniform[reserve[i] - 1]++;
    }

    for (let i = 0; i < hasUniform.length; i++) {
        // 유니폼이 없을 때 좌우 학생이 유니폼이 있을경우 빌려줌
        if (hasUniform[i] === 0) {
            if (hasUniform[i - 1] === 2) {
                hasUniform[i]++;
                hasUniform[i - 1]--;
            } else if (hasUniform[i + 1] === 2) {
                hasUniform[i]++;
                hasUniform[i + 1]--;
            }
        }

        // 유니폼이 1개이상 있으면 통과
        if (hasUniform[i] >= 1) {
            answer++;
        }
    }

    return answer;
}

console.log(solution(5, [2, 4], [1, 3, 5]));
console.log(solution(5, [2, 4], [3]));
console.log(solution(3, [3], [1]));
console.log(solution(7, [2, 3, 4], [1, 2, 3, 6]));

 

학생 수 만큼 배열을 만들고 유니폼 수를 1로 초기화 했다.

 

잃어버린 학생은 -1을 해주고 여벌이 있으면 +1을 해주었다.

 

유니폼이 없을 경우 좌우에 여벌이 있는 학생을 찾고 있으면 빌려주고

 

그 후에 유니폼이 있으면 answer를 증가시키는 방식으로 정답을 구하였다.

 

아무래도 학생 수가 적으니 for문을 여러번 하더라도

 

이렇게 명시적으로 코딩하는 게 낫다고 판단하였다.

 


 

Refactoring

function solution(n, lost, reserve) {

    // reserve의 얇은 복사본
    // slice()를 쓰면 reserve가 변할 때 tmp가 변하지 않지만
    // splice()를 쓰면 reserver가 변할 때 tmp가 변한다.
    let tmp = reserve.slice();

    for (let i in tmp) {
        // 잃어 버린 학생이 여분이 있는 학생인지 확인
        let key = lost.indexOf(tmp[i]);

        // 여분이 없으면 여분이 있는 학생이 잃어버린 학생에게 빌려준다
        if (key != -1) {
            lost.splice(key, 1);
            reserve.splice(reserve.indexOf(tmp[i]), 1);
        }
    }

    for (let i of reserve) {
        // 잃어버린 사람 한 칸 주위에 여분이 있는 사람이 있는지
        let key = lost.includes(i - 1)
            ? lost.indexOf(i - 1)
            : lost.indexOf(i + 1);

        // 있으면 잃어버린 사람 배열에서 삭제
        if (key != -1) {
            lost.splice(key, 1);
        }
    }

    return n - lost.length;
}

console.log(solution(5, [2, 4], [1, 3, 5]));
console.log(solution(5, [2, 4], [3]));
console.log(solution(3, [3], [1]));
console.log(solution(7, [2, 3, 4], [1, 2, 3, 6]));

Array.splice() Array.indexOf() 를 이용하는 방법도 있다.

 

주의할 점은 Array.splice()는 배열 자체를 변형 시키기 때문에 for문 조건을 바꿀 수 있으므로

 

Array.slice()를 이용해서 tmp라는 임시배열에 얕은 복사본을 저장하고 tmp로 for문을 돌린다는 점이다.

 

 

여분이 있는 학생 수 만큼 for문을 돌면서

 

잃어버린 학생이 여분이 있는 학생인지 확인하고(여분이 있으면 자신의 체육복을 사용하면 되기에)

 

여분이 있으면 자신이 입는 형식으로 잃어버렸는데 여분이 있는 학생과

 

여분이 있는데 잃어버리지 않은 학생을 가린다.

 

그 다음 잃어버린 사람 주위에 여분이 있는 사람이 있는지 확인하고 있으면 lost 배열에서 삭제한다.

 

총 학생수에서 잃어버린 학생수를 빼면 참가할 수 있는 학생 수가 된다.

 

 

 


 

Best

function solution(n, lost, reserve) {

    // 체육복을 잃어버렸으면서 여벌이 없는 경우
    const realLost = lost.filter((element) => !reserve.includes(element));

    // 여벌이 있으면서 체육복을 잃어버리지 않은 경우
    let realReserve = reserve.filter((element) => !lost.includes(element));

    // 학생 수(n) - 잃어버린 학생이 여벌을 못받은 경우(realLost.filter)
    return (
        // realLost.filter((lost) : 잃어버린 사람 중 여벌을 받을 수 없는 학생을 배열로 반환
        n -
        realLost.filter((lost) => {
            // lend : 체육복을 빌려줄 수 있는 경우 중 첫 번째 요소
            const lend = realReserve.find(
                // 잃어버린 사람의 1칸 주위에 빌릴 사람이 있는 경우
                (reverse) => Math.abs(reverse - lost) == 1,
            );

            // 빌려줄 수 있는 사람이 없으면 진짜 잃어버린 걸로 간주하고 lost를 return
            if (!lend) return lost;
            // 빌려 줬으면 reserve 배열에서 빌려준 사람 제외
            realReserve = realReserve.filter((reverse) => reverse !== lend);
        }).length
    );
}

console.log(solution(5, [2, 4], [1, 3, 5]));
console.log(solution(5, [2, 4], [3]));
console.log(solution(3, [3], [1]));
console.log(solution(7, [2, 3, 4], [1, 2, 3, 6]));

 

방식은 위와 비슷하나 for문을 이용하지 않고 Array.filter()를 이용하여

 

체육복을 잃어버렸으면서 여벌이 없는 경우와 여벌이 있으면서 체육복을 잃어버리지 않은 경우를 구해주었다.

 

그 다음, 잃어버린 학생 중 1칸 주위에 빌려 줄 수 있는 학생이 없는 경우만 필터링 하여

 

총 학생수에서 잃어버린 학생수를 뺀 값을 return하는 방법이다.

 

(마지막 방법은 통과가 안된다고 하네요! 위에 방법들로 이용해주세요!)

댓글