[프로그래머스-기초] 수열과 구간 쿼리 2

JiEun·2024년 1월 16일
0

코테/코플릿

목록 보기
49/56

수열과 구간 쿼리 2

문제 설명

정수 배열 arr와 2차원 정수 배열 queries이 주어집니다. queries의 원소는 각각 하나의 query를 나타내며, [s, e, k] 꼴입니다.

각 query마다 순서대로 s ≤ i ≤ e인 모든 i에 대해 k보다 크면서 가장 작은 arr[i]를 찾습니다.

각 쿼리의 순서에 맞게 답을 저장한 배열을 반환하는 solution 함수를 완성해 주세요.
단, 특정 쿼리의 답이 존재하지 않으면 -1을 저장합니다.

제한사항

1 ≤ arr의 길이 ≤ 1,000
0 ≤ arr의 원소 ≤ 1,000,000
1 ≤ queries의 길이 ≤ 1,000
0 ≤ s ≤ e < arr의 길이
0 ≤ k ≤ 1,000,000

입출력 예

arrqueriesresult
[0, 1, 2, 4, 3][[0, 4, 2],[0, 3, 2],[0, 2, 2]][3, 4, -1]

입출력 예 설명

입출력 예 #1
첫 번째 쿼리의 범위에는 0, 1, 2, 4, 3이 있으며 이 중 2보다 크면서 가장 작은 값은 3입니다.
두 번째 쿼리의 범위에는 0, 1, 2, 4가 있으며 이 중 2보다 크면서 가장 작은 값은 4입니다.
세 번째 쿼리의 범위에는 0, 1, 2가 있으며 여기에는 2보다 큰 값이 없습니다.
따라서 [3, 4, -1]을 return 합니다.

💻 내가 작성한 코드

function solution(arr, queries) {
    let result = []
    
    queries.forEach(([s,e,k]) => (
       result.push(arr.slice(s, e + 1).filter(el => el > k).sort((a,b) => a-b))
    ))
    
    return result.map((el) => el.length > 0 ? el[0] : -1)
    
}

이거 분명 day6에 푸는 문제 중 하나인데 난이도가 생각 보다 높아서 깜짝 놀랐다.
결국 다른 사람들의 질문 내용에서 힌트를 확인하면 풀었다..ㅠ

빈 배열인 result를 선언한다.
해단 변수에는 filter로 걸러진 값들이 들어 간다.

queries.forEach(([s,e,k]) => (
  result.push(arr.slice(s, e + 1).filter(el => el > k).sort((a,b) => a-b))
))

queries를 forEach를 통해 순환을 한다. 이 때 구조분해 할당으로 넣어 준다. [s,e,k]

[[s,e,k],[s,e,k],[s,e,k]] 처럼 표현된다고 생각하면 된다.

해당 코드는 네 가지로 나눠 볼 수 있다.

1. 배열 자르기

arr.slice(s, e + 1)

s기준으로 e만큼 자른 배열을 반환한다.
+1을 한 이유는 문제에서 요구하는 사항을 충족하기 위해서이다.

2-0. filter

arr.slice(s, e + 1).filter(el => el > k)

k보다 크면서 가장 작은 arr[i]를 찾습니다.
filter를 통해 조건을 충족하는 배열 요소만 반환한다.

2-1. filter

arr.slice(s, e + 1).filter(el => el > k).sort((a,b) => a-b)

2-0번까지 풀었다면 [[4,3],[4],[]] 의 배열을 반환한다.
여기서 최소값을 구해야하는데 이 부분에서 헤맸던 것 같다.

다른 사람들의 질문에서 sort메소드의 힌트를 얻어 해결 할 수 있었다.
a-b를 한 이유는 sort는 유니코드 기준으로 정렬하기 때문에
원하는 정렬이 안 나올 수 있다. 이때 a-b를 해줘야한다.

3. result에 push하기

result.push(arr.slice(s, e + 1).filter(el => el > k).sort((a,b) => a-b)

마지막으로 해당 배열을 result에 push한다.
그렇다면 [[3,4],[3],[]]라는 배열을 얻을 수 있다.

return result.map((el) => el.length > 0 ? el[0] : -1)

map메소드를 사용해 result를 순환하고 만약 el의 길이가 0보다 클 경우(값이 존재할 경우)
배열의 첫번째 값을 그렇지 않을 경우 -1를 반환한다.

여기서 문제점은

  • forEach내부에서 변수를 선언하려고 했으나 에러가 났다.
  • 두번째는 마지막 값을 반환할 때 el[0]보다 다른 방법이 없는지도 궁금하다.

💻 다른 사람이 작성한 코드

function solution(arr, queries) {
    return queries.map(([s, e, k]) => {
        let result = -1
        for (let i = s; i <= e; i += 1) {
            const v = arr[i]
            if (v <= k) continue
            result = result === -1 ? v : Math.min(result, v)
        }
        return result
    })
}

이분은 처음부터 result에 -1를 할당하고 값이 충족되지 않을 경우 바로 result를 반환하셨다.
그리고 Math.min()을 사용해 최소값을 구하셨다.

이분 코드를 보니 프로그래머스 코드에서 map, forEach, reduce 등의 메소드 내부에
변수선언을 할 수 있는 것 같다. (그럼 나는 왜 안 된건지...?)

Math.min()

  • 주어진 숫자들 중 가장 작은 값을 반환합니다.
  • 주어진 숫자들 중 가장 작은 값.
  • 만약 적어도 1개 이상의 인자값이 숫자형으로 변환이 불가능 한 경우 이 함수는 NaN 를 반환 합니다.
Math.min([value1[, value2[, ...]]])

-출처 : mdn

profile
💻 프론트엔드를 목표로 성장 중! (알아봤던 내용 등을 정리하기)

0개의 댓글