215. Kth Largest Element in an Array
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.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
1. Priority Queue:
O(nlogk) time complexity, O(k) space complexity.
public class Solution { public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> pq = new PriorityQueue<Integer>(k); for(int i : nums) { if(pq.size() < k) pq.add(i); else if(pq.peek() < i) { pq.remove(); pq.add(i); } } return pq.peek(); } }
2. Divide and Conquer solution.
Could be optimized to an average O(n) if use random number. Similar to Quick Sort. Can be used to find median of array.
public class Solution { public int findKthLargest(int[] a, int k) { int n = a.length; //kth largest is the (n-k+1)th smallest int p = quickSelect(a, 0, n - 1, n - k + 1); return a[p]; } // return the index of the kth smallest number int quickSelect(int[] a, int lo, int hi, int k) { // use quick sort's idea // put nums that are <= pivot to the left // put nums that are > pivot to the right int i = lo, j = hi, pivot = a[hi]; while (i < j) { if (a[i++] > pivot) swap(a, --i, --j); } swap(a, i, hi); // count the nums that are <= pivot from lo int m = i - lo + 1; // pivot is the one! if (m == k) return i; // pivot is too big, so it must be on the left else if (m > k) return quickSelect(a, lo, i - 1, k); // pivot is too small, so it must be on the right else return quickSelect(a, i + 1, hi, k - m); } void swap(int[] a, int i, int j) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } }
347. Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements.
For example,
Given [1,1,1,2,2,3]
and k = 2, return [1,2]
.
Note:
- You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
- Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
1. Base on heap.
Accumulate the count for each number, and then add the Map entry to a priority queue to keep k most frequent elements.
public class Solution { public List<Integer> topKFrequent(int[] nums, int k) { HashMap<Integer, Integer> m = new HashMap<>(); for (int i = 0; i < nums.length; ++i) { Integer count = m.get(nums[i]); if (count == null) m.put(nums[i], 1); else m.put(nums[i], count + 1); } PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(k, new Comparator<Map.Entry<Integer, Integer>>() { @Override public int compare(Map.Entry<Integer, Integer> a1, Map.Entry<Integer, Integer> a2) { return a1.getValue() - a2.getValue(); } }); for (Map.Entry<Integer, Integer> entry : m.entrySet()) { if (pq.size() < k) pq.add(entry); else if (pq.peek().getValue() < entry.getValue()) { pq.remove(); pq.add(entry); } } LinkedList<Integer> ret = new LinkedList<>(); while (!pq.isEmpty()) { ret.push(pq.remove().getKey()); } return ret; } }