와챠의 우당탕탕 코딩 일기장

[kotlin] 프로그래머스 - 명예의 전당(1) / PriorityQueue 본문

코딩 일기장/Android(Kotlin)

[kotlin] 프로그래머스 - 명예의 전당(1) / PriorityQueue

minWachya 2025. 4. 25. 21:57
반응형

문제 설명

"명예의 전당"이라는 TV 프로그램에서는 매일 1명의 가수가 노래를 부르고, 시청자들의 문자 투표수로 가수에게 점수를 부여합니다. 매일 출연한 가수의 점수가 지금까지 출연 가수들의 점수 중 상위 k번째 이내이면 해당 가수의 점수를 명예의 전당이라는 목록에 올려 기념합니다. 즉 프로그램 시작 이후 초기에 k일까지는 모든 출연 가수의 점수가 명예의 전당에 오르게 됩니다. k일 다음부터는 출연 가수의 점수가 기존의 명예의 전당 목록의 k번째 순위의 가수 점수보다 더 높으면, 출연 가수의 점수가 명예의 전당에 오르게 되고 기존의 k번째 순위의 점수는 명예의 전당에서 내려오게 됩니다.

이 프로그램에서는 매일 "명예의 전당"의 최하위 점수를 발표합니다. 예를 들어, k = 3이고, 7일 동안 진행된 가수의 점수가 [10, 100, 20, 150, 1, 100, 200]이라면, 명예의 전당에서 발표된 점수는 아래의 그림과 같이 [10, 10, 10, 20, 20, 100, 100]입니다.



명예의 전당 목록의 점수의 개수 k, 1일부터 마지막 날까지 출연한 가수들의 점수인 score가 주어졌을 때, 매일 발표된 명예의 전당의 최하위 점수를 return하는 solution 함수를 완성해주세요.

 

 

입출력 예

k score result
3 [10, 100, 20, 150, 1, 100, 200] [10, 10, 10, 20, 20, 100, 100]
4 [0, 300, 40, 300, 20, 70, 150, 50, 500, 1000] [0, 0, 0, 0, 20, 40, 70, 70, 150, 300]

 


접근 방법1

내 생각이 얼마나 단순했냐면

1. score랑 result랑 size도 같고 score 요소가 사용되네ㅋ? > map 사용

2. score 배열 잘라서 그 중 3번째로 작은 거 반환하면 되겟네? > slice, sort 사용

3. 매번 sort하는 거 시간 오래 걸릴텐데... > 근데 다른 아이디어도 없고... 함수를 단일 표현으로 끝낼 수 있는데... 단일 표현 함수 짧아서 멋진데...

라는 생각으로 아래 코드가 탄생함...ㅋ

 

답은 맞지만 당연하게도 시간이 너무 오래 걸림...ㅋ

class Solution {
    fun solution(k: Int, score: IntArray): IntArray = score.mapIndexed{ i, s ->
            if(i+1 < k) score.slice(0..i).sorted()[0]
            else score.slice(0..i).sortedDescending()[k-1]
        }.toIntArray()
}

 

 

접근 방법2

다른 사람 풀이를 보니까 PriorityQueue를 사용해서 문제를 해결하는 게 가장 효율적으로 보였음

시간 복잡도로만 봐도 나는... n인데 우선순위 큐 사용하면 logn임

시간도 적게 걸리고, 나의 경우 sort를 사용했는데 우선순위 큐를 사용하면 자동 정렬이 된다는 점에서 멋진 아이디어라고 생각했다...

 

1. score 배열 순서대로 한 요소씩 접근

2. k 이전 요소까지는 모두 순위에 오르니까 PriorityQueue에 저장

2-1. PriorityQueue는 자동으로 오름차순으로 정렬해주니까 peek를 했을 때 가장 작은 값을 얻을 수 있음

3. k 이후 요소부터는 peek 값보다 큰 요소만 PriorityQueue에 저장

4. 작은 값은 삭제

import java.util.*

class Solution {
    fun solution(k: Int, score: IntArray): IntArray {
        val pq = PriorityQueue<Int>()
        val answer = mutableListOf<Int>()
        
        score.forEach {
            if(pq.size < k) {
                pq.offer(it)
            } else {
                if(pq.peek() < it) {
                    pq.poll()
                    pq.add(it)
                }
            }
            answer.add(pq.peek())
        }
        
        return answer.toIntArray()
    }
}

PriorityQueue(우선순위 큐)

이진 트리 형태로 값을 오름차순 또는 내림차순으로 정렬할 수 있는 큐이다.

// 오름차순
val pq = PriorityQueue<Int>()
// 내림차순
val pq = PriorityQueue<Int>(Collections.reverseOrder())
  • 확인: 트리의 top값을 읽음(최소값 또는 최대값을 알아낼 수 있음)
    • element(): E
    • peek(): E?
    • element는 큐 비어있으면 NoSuchElementException 오류가 남. peek의 경우 null 반환. peek 쓰는 게 더 나음요
  •  삽입
    • add(element: E): Boolean
    • offer(element: E): Boolean
    • 둘 다 삽입, 삽입 후 성공하면 true 반환이지만
    • add는 삽입 시 여유 공간 없으면 IllegalStateException 오류가 남. offer는 걍 false 반환하기 때문에 offer 사용이 더 좋을 듯
  • 삭제
    • remove(): E
    • poll(): E?
    • remove는 큐 비어있으면NoSuchElementException 오류가 나지만 poll은 null 반환함. poll이 더 낫겟죠.

 

반응형
Comments