forked from rampatra/Algorithms-and-Data-Structures-in-Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKthLargestElementInArray.java
143 lines (123 loc) · 3.96 KB
/
KthLargestElementInArray.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package com.leetcode.heaps;
import com.rampatra.base.MaxHeap;
import java.util.PriorityQueue;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Level: Medium
* Link: https://leetcode.com/problems/kth-largest-element-in-an-array/
* Description:
* Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not
* the kth distinct element.
* <p>
* Example 1:
* Input: [3,2,1,5,6,4] and k = 2
* Output: 5
* <p>
* Example 2:
* Input: [3,2,3,1,2,4,5,5,6] and k = 4
* Output: 4
* <p>
* Note:
* You may assume k is always valid, 1 ≤ k ≤ array's length.
*
* @author rampatra
* @since 2019-08-19
*/
public class KthLargestElementInArray {
/**
* Runtime: <a href="https://leetcode.com/submissions/detail/252999497/">1 ms</a>.
*
* @param nums
* @param k
* @return
*/
public static int findKthLargest(int[] nums, int k) {
return heapSortUntilK(nums, k);
}
/**
* In heapsort, after each iteration we have the max element at the end of the array. Ergo, if we run the algorithm
* k times then we would have our kth largest element.
*
* @param a
* @param k
* @return
*/
public static int heapSortUntilK(int[] a, int k) {
buildMaxHeap(a);
int count = 0;
for (int i = a.length - 1; i > 0; i--) {
if (count++ == k) {
break;
}
swap(a, 0, i);
maxHeapify(a, 0, i);
}
return a[a.length - k];
}
/**
* Makes the array {@param a} satisfy the max heap property starting from
* {@param index} till {@param end} position in array.
* <p/>
* See this {@link MaxHeap#maxHeapify} for a basic version of maxHeapify.
* <p/>
* Time complexity: O(log n).
*
* @param a
* @param index
* @param end
*/
public static void maxHeapify(int[] a, int index, int end) {
int largest = index;
int leftIndex = 2 * index + 1;
int rightIndex = 2 * index + 2;
if (leftIndex < end && a[index] < a[leftIndex]) {
largest = leftIndex;
}
if (rightIndex < end && a[largest] < a[rightIndex]) {
largest = rightIndex;
}
if (largest != index) {
swap(a, index, largest);
maxHeapify(a, largest, end);
}
}
/**
* Converts array {@param a} in to a max heap.
* <p/>
* Time complexity: O(n) and is not O(n log n).
*/
private static void buildMaxHeap(int[] a) {
for (int i = a.length / 2 - 1; i >= 0; i--) {
maxHeapify(a, i, a.length);
}
}
/**
* When you poll() on a PriorityQueue the smallest number in the queue is removed. Based on this property, we can
* iterate over the entire array and in the end we would be left with the k largest element in the queue.
*
* @param nums
* @param k
* @return
*/
public static int findKthLargestUsingPriorityQueue(int[] nums, int k) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
for (int num : nums) {
priorityQueue.add(num);
if (priorityQueue.size() > k) {
priorityQueue.poll();
}
}
return priorityQueue.isEmpty() ? -1 : priorityQueue.peek();
}
private static void swap(int[] a, int firstIndex, int secondIndex) {
a[firstIndex] = a[firstIndex] + a[secondIndex];
a[secondIndex] = a[firstIndex] - a[secondIndex];
a[firstIndex] = a[firstIndex] - a[secondIndex];
}
public static void main(String[] args) {
assertEquals(5, findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 2));
assertEquals(3, findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 4));
assertEquals(5, findKthLargestUsingPriorityQueue(new int[]{3, 2, 1, 5, 6, 4}, 2));
assertEquals(3, findKthLargestUsingPriorityQueue(new int[]{3, 2, 1, 5, 6, 4}, 4));
}
}