Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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
Lines changed: 143 additions & 0 deletions
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+
}
Lines changed: 68 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /