Skip to content

Commit d971393

Browse files
committed
topk frequent elements
1 parent b2aba3e commit d971393

File tree

2 files changed

+211
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)