코딩테스트/프로그래머스

[코딩테스트 입문] Day 03 최빈값 구하기 (JavaScript)

Kim Minki 2022. 12. 25. 01:31

최빈값 구하기

문제 설명

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

제한사항

  • 0 < array의 길이 < 100
  • 0 ≤ array의 원소 < 1000

입출력 예

array result
[1, 2, 3, 3, 3, 4] 3
[1, 1, 2, 2] -1
[1] 1

입출력 예 설명

입출력 예 #1

  • [1, 2, 3, 3, 3, 4]에서 1은 1개 2는 1개 3은 3개 4는 1개로 최빈값은 3입니다.

입출력 예 #2

  • [1, 1, 2, 2]에서 1은 2개 2는 2개로 최빈값이 1, 2입니다. 최빈값이 여러 개이므로 -1을 return 합니다.

입출력 예 #3

  • [1]에는 1만 있으므로 최빈값은 1입니다.

나의 풀이

function solution(array) {
    let set = new Set(array);   // array에서 중복 제거
    let setArr = Array.from(set);   // 중복 제거한 배열 setArr
    let count = []  // 각 원소별 빈도를 기록하기 위한 배열 count 생성

    for(let k = 0; k < setArr.length; k ++) {
        count[k] = 0;   // 배열 count 0으로 초기화
    }

    for(let i = 0; i < setArr.length; i++) {
        for(let j = 0; j < array.length; j++) {
            if (setArr[i] == array[j]) {
                count[i] += 1;  // 각 원소별 중복될 때 마다 숫자를 카운트
            }
        }
    }

    let counted = 0;    // 가장 많은 빈도수를 저장하기 위한 변수
    for (let l = 0; l < count.length; l ++){    // 가장 많은 빈도수를 저장
        if (counted < count[l]){
            counted = count[l];
        }
    }

    let counts = 0; // 가장 많은 빈도수가 유일한지 확인
    for (let m = 0; m < count.length; m ++){
        if (counted == count[m]) {
            counts += 1;
        }
    }

    if (counts > 1){
        return -1;
    }
    else{
        for (let n = 0; n < count.length; n++){
            if (count[n] == counted){
                return setArr[n];
            }
        }
    }
}

풀이 설명

아이디어

  • 입력으로 들어오는 배열에서 요소의 중복을 제거한 배열을 생성하고 이를 이용해 입력으로 들어온 배열과 비교하여 요소별 빈도를 카운트 한다.

풀이 과정

  1. set객체를 이용해 입력으로 들어온 배열 array 요소의 중복을 제거한다.
    (이를 이용해 array의 원소별 빈도를 측정할 것.)
  2. setArr이라는 배열을 생성하여 set객체를 다시 배열로 저장한다.
    (아직 객체에 익숙치 않아 내가 사용하기 편한 배열로 변환한 것ㅠㅠ)
  3. 나중에 각 원소별 빈도를 기록하기 위해 배열 count생성
    (객체를 잘 활용할 줄 알았다면 생성하지 않았을 배열...ㅠㅠ)
  4. for 문을 이용해 배열 count를 배열 setArr의 크기, 각 요소는 모두 0으로 초기화
    (각 원소별 빈도를 기록하면 되므로 setArr의 크기만큼만 필요/각 요소를 모두 0으로 초기화 하지 않으면 나중에 수학 연산을 해도 undefined가 뜨기 때문)
  5. 이중 for 문을 이용해 하나의 setArr의 요소가 array의 전체 요소를 순차적으로 비교 후, 그 다음 setArr의 요소를 다시 array의 전체 요소를 순차적으로 비교. 이 과정을 setArr의 전체 요소만큼 반복
  6. 이 때 setArr의 요소와 같은 인덱스를 가진 count의 요소에 현재 setArr의 요소가 현재 비교 중인 array의 요소가 같을 때마다 1을 더해 빈도수를 카운트 한다.
    (나중에 이 인덱스를 매칭 시켜 setArr의 각 요소의 빈도를 count에서 찾기 위함이다. 애초에 객체를 사용했다면 정말 필요없는 과정이다😂)
  7. 가장 많은 빈도수를 저장하기 위해 변수 counted를 선언하고 0으로 초기화 한다.
  8. for 문을 통해 변수 counted와 빈도수가 저장된 배열 count의 각 요소와 비교해 현재 counted에 저장된 수보다 큰 값을 가지고 있는 경우 counted에 그 값을 저장한다.
    (이렇게 최종적으로 변수 counted에는 가장 큰 값 즉, 최빈값의 빈도가 저장될 것이다.)
  9. 문제의 조건에서 최빈값이 여러개면 -1을 return 하라고 했기 때문에 현재 구한 최빈값이 유일한지 확인하기 위해 변수 counts를 선언하고 0으로 초기화 한다.
  10. for 문을 통해 빈도수가 저장되어 있는 배열 count의 각 요소와 최빈값의 빈도가 저장되어 있는 변수 counted를 비교하여 같은 값이 나올 때마다 변수 counts의 값이 1씩 커지도록 한다.
  11. 이제 조건문을 통해 counts의 값이 1보다 크다면 즉, 최빈값이 유일하지 않고 여러개라면 -1을 return 하도록 한다.
  12. 그게 아니라면 즉, 최빈값이 유일하다면 for 문을 이용하여 각 요소별 빈도수가 저장되어 있는 배열 count의 각 요소와 가장 큰 빈도수가 저장되어 있는 변수 counted를 비교하여 그 값이 일치하는 경우, 배열 count의 요소와 같은 인덱스에 있는 배열 setArr의 요소를 최빈값으로 return 한다.
    (이를 위해 배열 array의 요소를 중복없이 저장한 배열 setArr와 그 요소의 빈도수를 저장한 배열 count의 인덱스를 일치시킨 것. 객체로 비유하자면 setArr이 key 값, count가 value 값이라 할 수 있다.)

array(입력)

1 1 2 2 3 4 4 5

setArr(key, 중복제거)

1 2 3 4 5

count(value, 각 요소별 빈도수)

2 2 1 2 1

느낀점

일단 객체를 활용하지 못한 점이 가장 뼈 아팠다. 현재 참여하고 있는 교육에서 그룹 스터디를 하며 코딩 테스트를 연습하고 있는데, 다른 팀원들의 풀이를 보니 모두 '객체'를 이용해 나의 풀이보다 간결하게 코드를 작성한 걸 볼 수 있었다. 객체라는 좋은 구조를 냅두고, 배열 2개를 이용해 그 구조를 흉내내려 했으니 당연한 결과이긴 하다ㅠㅠ 자바스크립트 문법에 대한 공부가 많이 많이 필요하다는 것을 느낀 문제였다.