글 작성자: 개발자 올라프

문제

 

nums는 숫자로 이루어진 배열이다. 가장 자주 등장한 숫자를 k갯수만큼 return해 주세요.

 

ex.

nums = [1, 1, 1, 2, 2, 3];
k = 2;
// return : [1, 2]

nums = [1];
k = 1;
// return [1]

 


 

풀이

 

function topK(nums, k) {
  let obj = {};
  
  nums.map(num => {
    if(obj[num]){
      obj[num] = obj[num]+1
    } else {
      obj[num] = 1
    }
  })
  
  let objSort = Object.keys(obj).sort((a,b) => {return obj[b]-obj[a]});
  return objSort.slice(0, k).map(e => Number(e));
}

 

객체 만들기

obj객체에 obj[num](nums 배열의 각 숫자값이 객체의 key값이 된다)이 있으면 1씩 증가하며, 만약 없다면 1을 할당한다.

만약 nums에 [3, 3, 3, 4, 4, 4, 4, 2, 2, 2, 2, 2, 1]이 담겨있다면 obj의 값은 {'1': 1, '2': 5, '3': 3, '4': 4}이 된다.

 

arr.sort()

obj의 값을 key에 담겨있는 값의 크기대로 내림차순으로 정렬하고자 한다. 이를 위해서 sort를 사용했다. sortarr.sort([compareFunction])과 같은 구문으로 되어 있으며 [compareFunction]을 생략해서 사용하면 요소를 문자열로 변환하고 유니코드 코드 포인트 순서로 문자열을 비교하여 정렬하게 된다.

 

[compareFunction]이 잘 이해가지 않는다면 다음 예시를 확인해야 한다. 문자열에서 apple은 banana 앞에 온다. 숫자에서 10은 3보다 뒤에 오지만, 문자열로 변환되면 10은 유니코드에서 3보다 앞에온다.

console.log( [10, 3, 24, 42, 41, 1].sort() );

// 결과 : [ 1, 10, 24, 3, 41, 42 ]

 

MDN에는 다음과 같이 정의되어 있다.

  • compareFunction(a, b)이 0보다 작은 경우 a를 b보다 낮은 색인으로 정렬합니다. 즉, a가 먼저옵니다.
  • compareFunction(a, b)이 0을 반환하면 a와 b를 서로에 대해 변경하지 않고 모든 다른 요소에 대해 정렬합니다.
  • compareFunction(a, b)이 0보다 큰 경우, b를 a보다 낮은 인덱스로 소트합니다.

 

첫 번째 정의를 해석하면 a-b < 0 이면 a < b 라는 의미이며, 이 경우에 낮은 색인인 a가 먼저온다는 것은 오름차순으로 정렬하는 것이다.

MDN에도 "문자열 대신 숫자를 비교하기 위해 compare 함수는 a에서 b를 뺄 수 있습니다. 다음 함수는 배열을 오름차순으로 정렬합니다"라고 쓰여있다. 내림차순으로 정렬하기 위해서 (a,b) => {return obj[b]-obj[a]}와 같이 입력했다.

 

k만큼 가져오기

 

slice를 사용하여 0번째 인덱스부터 k번째 인덱스(포함X)까지 가져온 배열을 map함수로 각 요소를 문자열에서 숫자로 바꾸어 숫자로 이루어진 배열을 반환하도록 하였다.