숫자배열에서 가장 자주 등장한 숫자를 인자만큼 반환하기

DongHee Kim·2021년 8월 26일
0

Algorithm

목록 보기
12/12
post-thumbnail

문제

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

예제 1
nums = [1,1,1,2,2,3]
k = 2
return [1,2]


예제 2
nums = [1]
k = 1
return [1]


풀이

(페어 풀이에서 풀이방안의 흐름을 제시하는 네비게이터 역할을 맡으신, 현재님의 풀이를 기반으로 공부했다 👍 )

사고의 흐름

Step.1 : 객체를 활용해 숫자의 등장 횟수 구하기

우선 숫자 배열에서 가장 자주 등장한 숫자를 찾아내야한다.
배열 값끼리의 비교가 필요할 땐, 객체를 만들어 비교하는게 편하다.

비어있는 객체 obj를 만들고, for문으로 값을 넣어준다.

  const obj = {};
  
  for (let i=0; i<nums.length; i++){
    (nums[i] in obj)
    ? obj[nums[i]] += 1
    : obj[nums[i]] =1
  }

for문은 삼항연산자를 사용했는데, 자세히 해석해보자면
배열의 i번째 값이 객체에 없으면 value에 1을 넣고,
배열의 i번째 값이 객체에 있으면 value에 1을 더한다.

따라서 nums = [1,1,2,2,2,3] 이라 하면 obj{1:2, 2:3, 3:1} 의 형태가 된다. 이 형태는 결국 {배열의 숫자값 : 그 숫자가 배열에서 등장한 횟수}를 뜻하고, 여기서 가장 자주 등장한 숫자는 2가 된다.


Step.2 : 가장 자주 등장한 값 찾아내기

{배열의 숫자값 : 그 숫자가 배열에서 등장한 횟수} 형태의 객체에서 우리가 원하는 건 가장 자주 등장한 배열의 숫자값이다.

객체의 value 기준으로 key를 내림차순 정렬하면 자주 등장한 순서대로 key값이 정렬된다.

  let newArr = Object.keys(obj).sort((a,b) => {
    return obj[b] - obj[a]
 })

Object.keys(객체명) 을 하면 객체의 key값만 배열로 반환해준다.
여기에 sort()메서드를 이용해 value값을 기준으로, key값의 배열을 내림차순 정렬했다.

sort(a,b) => {return obj[b] - obj[a]} 부분이 sort()메서드로 내림차순 정렬을 한 부분!

obj = {1:2, 2:3, 3:1}일 경우 위 과정을 진행하면 [2,1,3]이 반환된다.


Step.3 : 자주 등장한 값을 k갯수 만큼 반환하기

이제 정말 거의 다 왔다!
가장 자주 등장한 순서대로 정렬된 key값의 배열에서, 인자 k갯수 만큼 값을 반환해주면 된다.

 const result = newArr.slice(0,k).map(item => parseInt(item));
 return result;

(1) slice()메서드를 이용해 배열의 첫 index(0)부터 index(k) 전까지의 값을 반환한다. slice메서드의 인자는 (첫 시작 index, 직전까지의 값을 반환하는 index)이므로 가능한 풀이.

💥 주의 : 반환되는 값은 string이다.

예를 들어 [2,1,3].slice(0,2) = ['2','1']

(2) 값이 나오면 지금은 string이기 때문에 숫자로 바꿔주어야 한다.
배열의 값을 바꿔 새로운 배열로 만들어주는 map 메서드를 사용하고, 그 안에 각각의 값을 숫자로 바꾸는 건 parseInt 메서드를 사용했다.

위 값을 result 변수에 담고, 이를 return 해주면 풀이 완성!


정답 코드

function topK(nums, k) {
  const obj = {};
  
  for (let i=0; i<nums.length; i++){
    (nums[i] in obj)
    ? obj[nums[i]] += 1
    : obj[nums[i]] =1
  }
  
  let newArr = Object.keys(obj).sort((a,b) => {
    return obj[b] - obj[a]
  })
  
  const result = newArr.slice(0,k).map(item => parseInt(item));
 
  return result;  
}

느낀 점

  • 배열의 값을 서로 비교할 땐 더이상 for문 안에 i번째, (i+1)번째 값을 돌려보는 것만 떠올리지말고, 조건을 객체에 넣어서 비교하는 패턴을 머릿속에 저장하자

  • 객체의 속성을 조금 더 많이 알아두어야겠다.
    예를 들어 객체의 key값만 배열로 반환해주는 Object.keys(객체명) 라던지~

  • 알고리즘 문제는 배열을 많이 활용하다보니 오름차순, 내림차순으로 정렬해주는 sort() 메서드를 잘 알아둘 필요가 있다. 이것도 함께 저장!

profile
일상의 성실이 자존감을 만드는 성취주의자

0개의 댓글