1 <= k <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
heapify
bubbleDown
자료구조는 최대 힙 트리이지만, 복잡도 측면에서 이점을 얻기 위해 배열을 사용한다.
array
최대 힙 배열n
배열의 길이리프노드가 아닌 최초의 노드에서 맨 끝 노드 array[n-1]의 부모인 array[(n-2)/2]에서부터 array[0]까지 heapify()를 반복한다.
public void heapify() {
// array[n-1] -> array[n-2] -> .. -> array[0]
for (int i = (n - 2) / 2; i >= 0; i--) {
bubbleDown(i, n);
}
}
array[i]를 루트로 하는 서브 트리 array[i, i+1, .., n-1] 범위 내에서 힙 특성을 만족하도록 조정하면서 leaf 노드까지 내려간다.
public void bubbleDown(int i, int n) {
int child = 2 * i + 1; // 기본값은 leftChild
int rightChild = 2 * i + 2;
if (child <= n - 1) {
// 더 큰 자식 노드를 결정합니다.
if (rightChild <= n - 1 && array[rightChild] > array[child]) {
child = rightChild;
}
// 부모가 더 작은 경우, 교환하고 아래로 이동합니다.
if (array[i] < array[child]) {
int temp = array[i];
array[i] = array[child];
array[child] = temp;
bubbleDown(child, n);
}
}
}
class Solution {
private int[] array;
private int n; // 배열의 길이
/**
* array[i]에서부터 시작해서 부모인 array[(i-1)/2]를 기준으로 하는 서브 트리가
* Heap을 만족하도록 조정하면서 올라갑니다.
*
* @param i
*/
public void bubbleUp(int i) {
int child = i;
int parent = (i - 1) / 2;
if (parent >= 0 && array[child] > array[parent]) {
int temp = array[child];
array[child] = array[parent];
array[parent] = temp;
bubbleUp(parent);
}
}
public int findKthLargest(int[] nums, int k) {
// 최대 힙을 구성할 배열을 초기화
array = nums;
n = nums.length; // 배열의 길이 저장
// 배열을 최대 힙으로 변환
heapify();
// k번만큼 최대 힙에서 원소를 추출하여 버림
for (int i = 0; i < k - 1; i++) {
int temp = array[0];
array[0] = array[n - 1 - i];
array[n - 1 - i] = temp;
bubbleDown(0, n - 1 - i);
}
// k번째로 큰 값을 반환
return array[0];
}
/**
* array[i]를 루트(root)로 하는 서브 트리 array[i, i+1, .., n-1] 범위 내에서
* 힙 특성을 만족하도록 조정하면서 leaf 노드까지 내려갑니다.
*
* @param i
* @param n 범위의 끝 인덱스
*/
public void bubbleDown(int i, int n) {
int child = 2 * i + 1; // 기본값은 leftChild
int rightChild = 2 * i + 2;
if (child <= n - 1) {
// 더 큰 자식 노드를 결정합니다.
if (rightChild <= n - 1 && array[rightChild] > array[child]) {
child = rightChild;
}
// 부모가 더 작은 경우, 교환하고 아래로 이동합니다.
if (array[i] < array[child]) {
int temp = array[i];
array[i] = array[child];
array[child] = temp;
bubbleDown(child, n);
}
}
}
/**
* 리프노드가 아닌 최초의 노드에서 맨 끝 노드 array[n-1]의
* 부모인 array[(n-2)/2]에서부터 array[0]까지 heapify()를 반복합니다.
*/
public void heapify() {
// array[n-1] -> array[n-2] -> .. -> array[0]
for (int i = (n - 2) / 2; i >= 0; i--) {
bubbleDown(i, n);
}
}
}
시간 복잡도
공간 복잡도