오늘 뭐했냐/기억하면 좋을 문제들

최빈값 구하기 (객체 혹은 Map 활용)

스스로에게 2023. 5. 29. 21:43

최빈값은 주어진 값 중에서 가장 자주 나오는 값을 의미합니다. 정수 배열 array가 매개변수로 주어질 때, 최빈값을 return 하도록 solution 함수를 완성해보세요. 최빈값이 여러 개면 -1을 return 합니다.

 

이건 모르겠어서 다른 사람들의 풀이를 보고 해석하는 방향으로 잡았다 

 

1. 객체 활용

function solution(array) {
  // array의 길이가 1일 경우 갯수가 하나이기에
  // 그 값을 반환해준다.
  if (array.length === 1) return array[0];

  const obj = {};
  const answer = [];

  // array를 forEach() 반복문을 돌려
  // obj에 값이 없으면 값을 만들고 1을 넣어주고
  // obj에 값이 있으면 기존 값 +1을 해준다.
  array.forEach((n) => {
    obj[n] = ++obj[n] || 1;
  });

  // 값과 그 값의 갯수를 정의해 둔 obj를 array에 넣어준다.
  // ex) [[1, 1], [2, 1], [3, 3], [4, 1]]
  for (let key in obj) {
    answer.push([key, obj[key]]);
  }

  // answer 배열을 갯수 기준으로 내림차순 정렬을 해준다.
  // ex) [[3, 3], [4, 1], [2, 1], [1, 1]]
  answer.sort((a, b) => b[1] - a[1]);

  // 최빈값이 여러 개면 -1을 반환해야 하기 때문에 확인한다.
  if (answer[0][1] === answer[1][1]) return -1;

  // 여러개가 아니라면 정렬한 처음 값을 반환한다.
  return Number(answer[0][0]);
}

위 경우 문제 없어 보이지만 만약에 배열이 모두 같은 숫자로 주어진다면

[1, 1, 1, 1]의 경우 
// if (answer.length===1) return Number(answer[0][0])
if (answer[0][1] === answer[1][1]) return -1; // 여기서 런타임에러 발생 answer[1][1]이 없다

그래서 주석처리한 부분을 추가해 주어 런타임에러를 해결했다 

 

객체를 활용해서 이렇게 할 수 있다는 것을 처음 알았다

객체에 key를 추가해줄 때 key의 이름이 명확하다면 obj.key처럼 .을 사용해 추가해주는 경우는 알고 있었지만

여기선 obj[n]를 활용해 키가 어떻게 주어질 지 모르니 동적으로 추가해주었다 

이렇게 동적으로 추가해줄 수 있다는 사실을 처음 알게되었고

 

 || 연산자의 앞부분이 true인 경우 뒷부분을 연산하지 않는다는 것을 이용해

처음 obj[n]이 추가된 경우 초기값을 1로 만들고 이후에는 +1씩 해주게 만들었다

 

이렇게 만들어진 객체를 for in 문을 통해 key -value가 묶인 배열이 하나씩 들어간 이차원배열로 만든 다음

빈도수값 순으로 정렬을 해 가장 빈도수가 큰 배열이 두 개 이상인지 판단해 값을 반환했다

추가로 key로 사용되었던 주어진 배열의 요소는 문자열로 바뀌었기 때문에 마지막에 Number()로 숫자형으로 바꿔준다

 

2. Map 활용

function solution(array) {
    let myMap = new Map();
    for (let n of array) myMap.set(n, (myMap.get(n) || 0)+1);
    myMap = [...myMap].sort((a,b)=>b[1]-a[1]);
    return myMap.length === 1 || myMap[0][1] > myMap[1][1] ? myMap[0][0] : -1;
} 


 console.log([...myMap]) // [ [ 3, 3 ], [ 1, 1 ], [ 2, 1 ], [ 4, 1 ] ]
 console.log(myMap) // [ [ 3, 3 ], [ 1, 1 ], [ 2, 1 ], [ 4, 1 ] ]

 Map자료 구조를 활용해서 해결한 코드이다

for of를 활용해서 myMap에 키캆쌍을 추가해주었으며 마찬가지로 ||를 이용해 초기값은 1로 시작되었다 

위와 다른 점은 myMap.set(n, (myMap.get(n) || 0)+1) 부분인데  (++myMap.get(n) || 1)로 처리하면 에러가 발생한다

그래서 카운트를 늘려갈 땐 0부터 1씩 추가하는 식으로 해야할 것 같다 

 

순서 정렬을 위해 .sort()를 사용할 때 같은 똑같이 출력되는데 왜 스프레드 문법을 쓸까 생각해봤는데 아무래도 sort()는 배열의 메소드라서 입력값이 배열로 주어져야해서 그런 것으로 해석된다

 

이번 문제처럼 배열이 주어지지 않더라도 내가 배열로 바꾼 다음에 위 방법을 활용할 수도 있을 것이고 Map와 객체에 대해서 다시 생각해보게 되었다