The journey to becoming a developer

My future is created by what I do today, not tomorrow.

Algorithms/Programmers

[프로그래머스 Level 1] 제일 작은 수 제거하기 (자바스크립트)

Millie 2021. 10. 7. 12:05

Description

정수를 저장한 배열, arr에서 가장 작은 수를 제거한 배열을 리턴하는 함수, solution을 완성해주세요. 단, 리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴하세요. 예를 들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴하고, [10] 면 [-1]을 리턴합니다.

Constraints

arr은 길이 1 이상인 배열입니다.
인덱스 i, j에 대해 i ≠ j이면 arr[i] ≠ arr[j] 입니다.

My Solution

처음엔 예시만 보고 "배열을 오름차순으로 정렬한 다음, 마지막 요소를 pop으로 제거하면 되겠다"라고 생각했는데, 더 생각해 보니 아니었다. 그렇게 되면 정렬된 배열이 나오게 되는데 정렬은 문제에 포함되지 않는다. 그래서 다른 방법을 써야 한다.

function solution(arr) {
    arr.splice(arr.indexOf(Math.min(...arr)), 1);
    return arr.length ? arr : [-1];
    }
  1. 배열의 최솟값을 알아낼 때는 내장 함수인 Math.min()을 이용한다. 이때 Math.min은 배열이 아닌 숫자들의 목록을 인수로 받아야 한다. 배열 자체를 인수로 받을 순 없다. 그래서 전개 문법(Spread syntax)을 사용한다.
  2. 이렇게 얻어낸 최솟값의 인덱스를 arr.indexOf(최솟값)으로 찾아준다.
  3. splice를 통해 (시작 인덱스, 삭제 개수)를 인자로 넘겨 줘서 최솟값을 삭제해준다. splice는 원본을 변경한다.
  4. 이렇게 변경된 배열이 빈 배열이라면 [-1]을 리턴하고, 그렇지 않다면 변경된 배열을 리턴한다.

 

Other's Solution 1

function solution(arr) {
  if (arr.length === 1) return [-1];
  let min;
  arr.reduce((acc, cur) => (min = cur > acc ? acc : cur));
  return arr.filter(e => e !== min);
}

풀이 출처(블로그)

  1. array의 요소가 하나라면 [-1]을 반환하고 즉시 함수를 종료한다.
  2. reduce로 이전 값과 현재 값을 비교하여 가장 작은 수를 알아낸다.
  3. filter로 가장 작은 수를 제외한 나머지 수로 이루어진 배열을 만들어 반환한다.

reduce는 배열의 모든 요소의 합을 구할 때 유용하게 썼었는데, 이런 식으로 Math.min 내장 함수 대신 최솟값을 구할 때도 응용해서 쓸 수 있다는 것을 알았다. MDN에 보면 정말 많은 예제들과 활용법이 있는데, 배워 나가야겠다.

 

filter는 주어진 함수의 테스트를 통과하는 모든 요소를 모아서 새로운 배열로 반환해준다.

 

Other's Solution 2

function solution(arr) {
    if (arr.length === 1 ) {
        return [-1]
    }
    const minValue = Math.min.apply(null, arr)
    const index = arr.findIndex(value => value === minValue)
    arr.splice(index, 1)
    return arr
}

이 풀이를 통해 apply, findIndex 메서드를 좀 더 공부할 수 있었다.

apply

apply는 주어진 this값과 배열로 제공되는 인자로 함수를 호출한다.

전개 문법 대신에 이런 방법으로 Math.min을 호출해서 동일한 결과를 얻어낼 수 있다.

apply는 call과 거의 동일한데 apply는 배열을 1개만 받아서 처리할 수 있지만, call은 여러 개의 배열을 받을 수 있다.

findIndex

findIndex는 주어진 판별 함수를 만족하는 배열의 첫 번째 요소에 대한 인덱스를 반환한다. 만족하는 요소가 없으면 -1을 반환한다.

여기서는 배열의 요소가 바로 윗줄에서 구했던 최솟값과 같은지에 대한 조건을 콜백 함수로 전달하고 있고, 이 조건이 만족되면 최솟값의 인덱스를 반환하도록 했다.

참고로 find는 인덱스 대신 값 자체를 반환한다.


간단한 알고리즘이지만 서로 다른 메서드를 사용해서 다양한 풀이가 나올 수 있다는 것을 알게 되었다. 풀었다고 끝이 아니라 다른 사람들의 풀이를 보면서 배워나가는 건 정말 필수적이라고 생각했다.

여기서만 해도 정말 많이 배워나갔다. spread syntax, Math.min, splice, indexOf, apply, findIndex, (+call, find), reduce, filter 등등. 아직 이런 것들을 깊게 안다고는 할 수 없어서, 더 많이 접해보면서 익숙하게 만들어야겠다.

참고 자료

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

https://ko.javascript.info/rest-parameters-spread

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/apply