Practice for coding test

프로그래머스 - Level 2. 귤 고르기 / JavaScript (js)

Gray Park 2023. 2. 25. 11:30
728x90
반응형

문제설명

문제분석

이 문제는 입력값으로 주어진 tangerine에 포함된 요소의 갯수를 카운트하고, 큰 카운트들의 합이 k 이상이 될 때, 이 카운트의 갯수를 리턴하는 문제입니다. 조금 복잡해보이니 정리하자면 다음과 같습니다.

  • tangerine에서 각 요소를 순회한다.
  • 이때 각 요소의 값이 몇 번 등장했는지 카운트한다.
  • 각 요소의 값 중 큰 값을 기준으로 정렬한다.
  • k에서 큰 값을 차례대로 빼주면서 k가 0보다 작거나 같게 만든다.
  • 이때 값을 빼줄 때마다 리턴할 값을 1씩 증가한다.

이해하기 쉽게 코드작성하기

function solution(k, tangerine) {
    const countObj = {};
    let count = 0;
    let prev = -1;
    
    // 귤을 크기별로 정렬
    tangerine.sort((a, b) => a - b);
    // 크기에 따라 몇 번 등장하는지 카운트
    tangerine.forEach(x => {
        if(countObj[x] === undefined) {
            countObj[x] = 0;
        }
        countObj[x] += 1;
    });
    // 많이 등장한 순서에 따라 Asc 정렬(pop 할 거라서)
    tangerine = tangerine.sort((a, b) => countObj[a] - countObj[b]);
    
    // k가 0이될 때까지 많이 등장한 값을 제거
    // 이때 값이 변경될 때마다 count 증가
    while(k > 0) {
        const now = tangerine.pop();
        if(prev !== now) {
            count++;
        }
        prev = now;
        k--;
    }
    
    return count;
}

귤을 크기별로 정렬하고, 크기에 따라 몇 번 등장하는지 카운트합니다. 그러고 다시 많이 등장한 순서에 따라 정렬하고, 요소를 하나씩 제거하면서 k를 줄여줍니다. 이때 요소의 값이 이전 값과 달라질 때마다 카운트를 올려줍니다.

 

위 과정에서 굳이 요소를 하나씩 제거할 필요가 있나 싶습니다. 조금 수정하면 다음과 같습니다.

function solution(k, tangerine) {
    const countObj = {};
    let count = 0;
    let prev = -1;
    
    tangerine.sort((a, b) => a - b);
    tangerine.forEach(x => {
        if(countObj[x] === undefined) {
            countObj[x] = 0;
        }
        countObj[x] += 1;
    });
    tangerine = tangerine.sort((a, b) => countObj[a] - countObj[b]);

	// 가장 큰 값이 처음 등장하는 idx부터 마지막 요소까지의 길이만큼 k에서 제거
    while(k > 0) {
        const now = tangerine[tangerine.length-1];
        const idx = tangerine.indexOf(now);
        if(prev !== now) count++;
        prev = now;
        k -= tangerine.length - idx;
        tangerine = tangerine.slice(0, idx);
    }
    
    return count;
}

이렇게 작성하고 나니, countObj를 이용해 이미 카운트해두었는데, 이를 이용하면 코드가 좀 더 간결해지지 않을까 싶습니다. 변경한 코드는 다음과 같습니다.

반응형
function solution(k, tangerine) {
    const tangerineCount = {};
    let count = 0;
    
    tangerine.forEach(x => tangerineCount[x] === undefined ? tangerineCount[x] = 1 : tangerineCount[x] += 1);
    
    const keys = Object.keys(tangerineCount).sort((a, b) => tangerineCount[b] - tangerineCount[a]);
    
    while(k > 0) {
        const key = keys.shift();
        count++;
        k -= tangerineCount[key];
    }
    
    return count;
}

객체에 이미 값을 저장해뒀으므로, 이 객체의 값을 정렬하고 k에서 빼주는 형태로 수정했습니다. countObj는 조금 불명확한 것 같아 조금 더 명확하게 객체 리터럴의 변수명을 변경했습니다. 어차피 객체의 값을 비교하는데 굳이 key는 필요없을 것 같습니다. (key는 위에서 tangerine을 정렬하고, index를 찾을 때 사용했습니다.) Object.keys를 Object.values로 변경해보겠습니다.

최종 코드는 다음과 같습니다.

function solution(k, tangerine) {
    const tangerineCount = {};
    let count = 0;
    
    tangerine.forEach(x => tangerineCount[x] === undefined ? tangerineCount[x] = 1 : tangerineCount[x] += 1);
    
    const values = Object.values(tangerineCount).sort((a, b) => a - b);
    
    while(k > 0) {
        count++;
        k -= values.pop();
    }
    
    return count;
}
728x90
반응형