1.优先队列

image.pngimage.png

2.优先队列的实现

  1. public interface Queue<E> {
  2. int getSize();
  3. Boolean isEmpty();
  4. void enqueue(E e);
  5. E dequeue();
  6. E getFront();
  7. }

2.1 使用堆实现

  1. // 使用堆实现优先队列
  2. public class PriorityQueue <E extends Comparable<E>> implements Queue<E>{
  3. private MaxHeap<E> data;
  4. // 若传入数组,可以直接使用堆进行堆化
  5. public PriorityQueue(){
  6. data = new MaxHeap<>();
  7. }
  8. @Override
  9. public int getSize(){
  10. return data.getSize();
  11. }
  12. @Override
  13. public boolean isEmpty(){
  14. return data.isEmpty();
  15. }
  16. @Override
  17. // O(h)
  18. public void enqueue(E e){
  19. data.add(e);
  20. }
  21. @Override
  22. // O(h) h 为 树的高度
  23. public E dequeue(){
  24. return data.remove();
  25. }
  26. @Override
  27. // O(1)
  28. public E getFront(){
  29. return data.findMax();
  30. }
  31. }

2.2使用LinkedList实现

  1. // 使用LinkedList实现
  2. // 对于优先队列,需要在尾部加入,头部删除
  3. // 所以 enqueue 为 O(1)
  4. public class PriorityQueue <E extends Comparable<E>> implements Queue<E>{
  5. private Linkedlist<E> data;
  6. // 将数组放入,实现队列,由于链表的 add 不存在
  7. public PriorityQueue(E[] arr){
  8. //先将数组排序
  9. QuickSort.sort(arr);
  10. data = new LinkedList<>();
  11. for(int i = 0; i < arr.length; i++){
  12. data.addFirst(arr[i]);
  13. }
  14. }
  15. @Override
  16. public int getSize(){
  17. return data.getSize();
  18. }
  19. @Override
  20. public Boolean isEmpty(){
  21. return data.isEmpty();
  22. }
  23. @Override
  24. public void enqueue(E e){
  25. // 这里需要进行比较,找到元素在 链表中的位置,再使用add(e, index)
  26. // 在 index 处插入
  27. data.sort(e);
  28. }
  29. // 对链表进行排序
  30. public void sort(E value){
  31. E target = value;
  32. Node prev = dummyHead;
  33. for(int i = 0; i < size; i++){
  34. prev = prev.next;
  35. if(target.compareTo(prev.e) >= 0){
  36. add(i,target);
  37. break;
  38. }
  39. }
  40. }
  41. @Override
  42. public E dequeue(){
  43. E res = data.getFront();
  44. data.removeFirst();
  45. return res;
  46. }
  47. @Override
  48. public E getFront(){
  49. return data.getFront();
  50. }
  51. }

2.3 使用数组实现

  1. // 使用 可变数组实现
  2. public class PriorityQueue <E extends Comparable<E>> implements Queue<E>{
  3. private Array<E> data;
  4. // 将数组放入,实现队列,由于链表的 add 不存在
  5. public PriorityQueue(E[] arr){
  6. //先将数组排序
  7. QuickSort.sort(arr);
  8. data = new Array<>();
  9. // 从大到小
  10. for(int i = 0; i < arr.length; i++){
  11. data.addFirst(arr[i]);
  12. }
  13. }
  14. @Override
  15. public int getSize(){
  16. return data.getSize();
  17. }
  18. @Override
  19. public Boolean isEmpty(){
  20. return data.isEmpty();
  21. }
  22. @Override
  23. public void enqueue(E e){
  24. // 这里需要进行比较,找到元素在 链表中的位置,再使用add(e, index)
  25. // 在 index 处插入
  26. for(int i = 0; i < data.getSize();i++){
  27. if(data.get(i).compareTo(e) <= 0){
  28. data.add(i,e);
  29. break;
  30. }
  31. }
  32. }
  33. @Override
  34. public E dequeue(){
  35. E res = data.getFront();
  36. data.removeFirst();
  37. return res;
  38. }
  39. @Override
  40. public E getFront(){
  41. return data.getFront();
  42. }
  43. }

3.leetcode 相关问题

1.topK 问题:

取出最大或者最小的k个元素
https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/
image.png

  1. class Solution {
  2. public int[] getLeastNumbers(int[] arr, int k) {
  3. // 优先队列默认最小堆
  4. Queue<Integer> queue = new PriorityQueue<>(Collections.reverseOrder());
  5. // 由于优先队列在add时会进行排序,所以会由大到小进行排序
  6. for(int nu: arr){
  7. queue.add(nu);
  8. }
  9. int[] res = new int[k];
  10. for(int i = 0; i < k ; i++){
  11. res[i] = queue.remove();
  12. }
  13. return res;
  14. }
  15. }
  16. //优化
  17. // 先任意加入 k 个元素,最大的在前面,一旦有小于最大的就加入

2. SelectK 问题

image.png

  1. // 使用优先队列
  2. class Solution {
  3. public int findKthLargest(int[] nums, int k) {
  4. // 默认最小堆
  5. Queue<Integer> queue = new PriorityQueue<>();
  6. // 加入前k个数
  7. for(int i = 0; i < k; i++){
  8. queue.add(nums[i]);
  9. }
  10. // 然后遍历后面的元素,假如有数比这个大,则插入
  11. // 最后队列的顶就是第k大的值(加入过程中会进行排序)
  12. for(int i = k ; i < nums.length; i++){
  13. while(!queue.isEmpty() && nums[k] > queue.peek()){
  14. queue.remove();
  15. queue.add(nums[k]);
  16. }
  17. }
  18. }
  19. }

4.对于不同的队列:

Java 实现的标准优先队列:

若没有传入比较器,则默认最小堆,否则为最大堆