본문 바로가기

공부/Algorithm

[JS] 귤 고르기 (Map 사용하기)

문제 풀이

해당 문제에서 구해야 하는 것은 귤 k개를 고를 때, 귤의 크기 차이를 최소화 하는 것이다.

아이디어는 단순하게, 크기가 많은 것부터 선택해야 차이가 나는 귤의 종류를 최소화할 수 있다.

주어진 배열에 크기에 따른 귤의 개수를 알아야 하므로 Map을 사용해서 구현했다.

 

Map

key-value 쌍의 형태로 데이터를 저장하는 자료구조이다.

객체와 비슷하지만, 객체의 key 타입은 문자열과 Symbol만 가능하지만, Map은 문자열, 함수, 배열 등 모든 자료형이 가능하다는 차이점이 있다.

 

1. key-value 형태의 이터러블을 인수로 전달

const map = new Map(); // Map(0) {}
const map = new Map([['k1', 'v1'], ['k2', 'v2']]) // Map(2) {'k1'=>'v1', 'k2'=>'v2"}

이때 동일한 값이 들어가면, 나중에 입력한 값으로 갱신된다. 

 

2. size (= map의 요소 개수)

 

3. set  

map 객체를 반환하므로 체이닝 가능

const map = new Map()
map.set('k1', 'v1').set('k2', 'v2')

 

4. keys, values, entries

const map = new Map();
map.set('a', 1);
map.set('b', 2);

console.log(map.entries()); // 출력: MapIterator { 'a' => 1, 'b' => 2 }

const entriesArray = [...map.entries()];
console.log(entriesArray); // 출력: [ ['a', 1], ['b', 2] ]

 

[...map] == [...map.entries()]

console.log로 출력해보면 둘의 결과가 동일하게 나온다

하지만, entries 메소드를 호출함으로써 "나는 Map의 [키, 값] 쌍을 명확하게 다루고 있다" 라는 의도를 명확하게 하기 위해서 사용한다.

 

map: Map 객체 자체로, 그 자체로는 이터러블이지만 순회하거나 배열로 변환하려면 메서드가 필요하다.

map.entries(): Map 객체의 [키, 값] 쌍을 이터레이터 형태로 반환하는 메서드로 배열로 변환하거나 반복할 수 있다. 


첫번째 코드

function solution(k, tangerine) {
    var answer = 0;
    const map = new Map(); // Map 생성
    
    tangerine.forEach(t => {
        if(map.has(t)) map.set(t, map.get(t)+1) // t키가 있으면 해당 value+1
        else map.set(t, 1) // 없으면 1로 초기화
    })
    
    const sortedMap = [...map].sort((a, b) => b[1] - a[1]); // value 값으로 내림차순 정렬
    
    for(let i=0; i<sortedMap.length; i++){ // 정렬된 배열을 순회하면서
        if(k<=0) break; 
        k-=sortedMap[i][1] // 총 귤의 개수에서 해당 크기의 귤의 개수만큼 빼기
        answer+=1;
    }
        
    return answer;
}

해당 코드의 개선사항은 다음과 같다.


개선 코드

1. reduce를 사용해서 코드를 간결하게 만들었다.

2. map.entries 메소드를 사용해서 의도를 명확히했다.

3. for..of를 사용해서 정렬된 배열을 순회했다 (배열 구조분해 사용)

function solution(k, tangerine) {
    var answer = 0;
    const map = tangerine.reduce((acc, t) => acc.set(t, (acc.get(t) || 0) + 1), new Map());
    const sortedTangerines = [...map.entries()].sort((a, b) => b[1] - a[1]);
    
    for (const [_, count] of sortedTangerines) {
        if (k <= 0) break; 
        k -= count;        
        answer++;          
    }
    
    return answer;
}

 

이전 코드에서 가장 길었던 마지막 케이스를 보면 시간은 줄어들었는데, 27~30 테스트에서 시간이 늘어났다(오잉)

어쨌든 entries 메소드가 호출되어서 그런가

 

 

프로그래머스

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

programmers.co.kr