当前位置:   article > 正文

编程之美3.7:队列中取最大值操作问题_修改1中的“出队”函数dequeue,使得每次出队的是队列元素中的最大值;

修改1中的“出队”函数dequeue,使得每次出队的是队列元素中的最大值;

题目描述:
假设有这样一个拥有3个操作的队列:
a. EnQueue(v):将v加入队列中;
b. DeQueue:使队列中的队首元素删除并返回次元素;
c. MaxElement:返回队列中的最大元素

请设计一种数据结构预算法,让MaxElement操作的时间复杂度尽可能低。

解法一:
新建一个队列,然后遍历取得最大值。时间复杂度O(n)。

  1. public class Solution1 {
  2. public static void EnQueue(int v,Queue<Integer> a) {
  3. a.add(v);
  4. }
  5. public static int DeQueue(Queue<Integer> a) {
  6. int v = a.poll();
  7. return v;
  8. }
  9. public static int MaxElement(Queue<Integer> a) {
  10. Queue<Integer> temp = new LinkedList<>();
  11. int max = a.peek();
  12. while(a.poll()!=null) {
  13. int v = a.poll();
  14. if(v > max)
  15. max = v;
  16. temp.add(v);
  17. }
  18. return max;
  19. }
  20. public static void main(String[] args) {
  21. Queue<Integer> a = new LinkedList<>();
  22. EnQueue(1, a);
  23. EnQueue(4, a);
  24. System.out.println(DeQueue(a));
  25. EnQueue(5, a);
  26. EnQueue(1, a);
  27. EnQueue(2, a);
  28. System.out.println(MaxElement(a));
  29. }
  30. }

这里可以做一点改进,在EnQueue(v)中加入比较过程,从而不用重新新建一个队列。
  1. import java.util.LinkedList;
  2. import java.util.Queue;
  3. public class Solution1 {
  4. public static int EnQueue(int max,int v,Queue<Integer> a) {
  5. a.add(v);
  6. if(v > max)
  7. max = v;
  8. return max;
  9. }
  10. public static int DeQueue(Queue<Integer> a) {
  11. int v = a.poll();
  12. return v;
  13. }
  14. public static void MaxElement(int max) {
  15. System.out.println(max);
  16. }
  17. public static void main(String[] args) {
  18. Queue<Integer> a = new LinkedList<>();
  19. int max = 1;
  20. max = EnQueue(max,1, a);
  21. max = EnQueue(max,4, a);
  22. System.out.println(DeQueue(a));
  23. max = EnQueue(max,5, a);
  24. max = EnQueue(max,1, a);
  25. max = EnQueue(max,2, a);
  26. MaxElement(max);
  27. }
  28. }

解法二:
用最大堆来维护队列中的元素。时间复杂度O(1),空间复杂度O(logn)。
这里没有用堆排序,用了类似于LinkedHashMap的实现方式。
  1. import java.util.ArrayList;
  2. public class Solution2 {
  3. public static void main(String[] args){
  4. HeapQueue heapQueue = new HeapQueue();
  5. heapQueue.enQueue(11);
  6. heapQueue.enQueue(78);
  7. heapQueue.enQueue(30);
  8. heapQueue.enQueue(9);
  9. heapQueue.enQueue(8);
  10. heapQueue.enQueue(4);
  11. heapQueue.enQueue(7);
  12. heapQueue.enQueue(15);
  13. System.out.println(heapQueue);
  14. System.out.println(heapQueue.deQueue());
  15. System.out.println(heapQueue);
  16. System.out.println(heapQueue.maxValue());
  17. }
  18. }
  19. class HeapQueue{
  20. MaxHeap max = new MaxHeap();
  21. public void enQueue(int x) {
  22. max.insert(x);
  23. }
  24. public int deQueue(){
  25. int temp = max.head.value;
  26. max.deleteLast();
  27. return temp;
  28. }
  29. public int maxValue(){
  30. return max.getMax();
  31. }
  32. public String toString() {
  33. return max.toString();
  34. }
  35. }
  36. class MaxHeap {
  37. private ArrayList<Node> array = new ArrayList<>(); //用来堆排序
  38. Node tail; //记录链表尾
  39. Node head;
  40. //删除最后一个元素 O(2n)
  41. public void deleteLast() {
  42. Node temp = head;
  43. head = head.next;
  44. array.remove(temp);
  45. }
  46. //获取最大值
  47. public int getMax(){
  48. return array.get(0).value;
  49. }
  50. //插入一个值 O(2n)
  51. public void insert(Integer x){
  52. Node temp = new Node();
  53. temp.value = x;
  54. if(tail == null){
  55. tail = temp;
  56. head = temp;
  57. } else {
  58. tail.next = temp;
  59. tail = temp;
  60. }
  61. int i = 0;
  62. for (; i < array.size(); i++) {
  63. if(array.get(i).value < temp.value)
  64. break;
  65. }
  66. array.add(i, temp);
  67. }
  68. //用于显示结果(先显示排序结果,后显示插入顺序,以**为分割)
  69. public String toString() {
  70. StringBuffer sb = new StringBuffer();
  71. Node temp = head;
  72. for (int i = 0; i < array.size(); i++)
  73. sb.append(array.get(i).value + " ");
  74. sb.append("**");
  75. while(temp!= null){
  76. sb.append(" " + temp.value);
  77. temp = temp.next;
  78. }
  79. return new String(sb);
  80. }
  81. //用链表来记录插入顺序,参考LinkedHashMAp
  82. class Node{
  83. Integer value;
  84. Node next;
  85. }
  86. }

解法三:
维护一个最大值序列保证Max操作的时间复杂度是O(1)。用栈实现队列,栈的Max操作比较容易实现。
  1. public class Solution3 {
  2. public static void main(String[] args) {
  3. //定义一个Stack类
  4. Stack s = new Stack(5);
  5. s.push(12);
  6. s.push(3);
  7. s.push(5);
  8. s.push(9);
  9. s.push(6);
  10. s.push(36);
  11. System.out.println(s.Max());
  12. s.Pop();
  13. System.out.println(s.Max());
  14. //定义一个Queue_T类,用Stack实现
  15. Queue_T q = new Queue_T();
  16. q.EnQueue(3);
  17. q.EnQueue(4);
  18. q.EnQueue(2);
  19. System.out.println(q.Max());
  20. q.DeQueue();
  21. q.EnQueue(5);
  22. System.out.println(q.Max());
  23. }
  24. private static class Stack {
  25. private static int maxStackItemIndex;
  26. private static int stackTop;
  27. private static int[] link2NextMaxItenm; //最大值序列
  28. private static int[] stackItem;
  29. private static int maxn;
  30. public Stack(int maxn) {
  31. stackTop = -1;
  32. maxStackItemIndex = -1;
  33. link2NextMaxItenm = new int[maxn];
  34. stackItem = new int[maxn];
  35. this.maxn = maxn;
  36. }
  37. void push(int x) {
  38. if (stackTop >= maxn-1) {} //超出栈的最大存储量
  39. else {
  40. stackTop++;
  41. stackItem[stackTop] = x;
  42. if (x > Max()) {
  43. link2NextMaxItenm[stackTop] = maxStackItemIndex;
  44. maxStackItemIndex = stackTop;
  45. } else {
  46. link2NextMaxItenm[stackTop] = -1;
  47. }
  48. }
  49. }
  50. int Pop(){
  51. int ret;
  52. if(stackTop <0){
  53. return -1;
  54. }else{
  55. ret = stackItem[stackTop];
  56. if(stackTop == maxStackItemIndex){
  57. maxStackItemIndex = link2NextMaxItenm[stackTop];
  58. }
  59. stackTop--;
  60. return ret;
  61. }
  62. }
  63. int Max() {
  64. if (maxStackItemIndex >= 0) {
  65. return stackItem[maxStackItemIndex];
  66. } else {
  67. return -1;
  68. }
  69. }
  70. }
  71. }

Queue_T类:
  1. import java.util.Enumeration;
  2. class Queue_T{
  3. private java.util.Stack<Integer> stackA;
  4. private java.util.Stack<Integer> stackB;
  5. private int max_index;
  6. public Queue_T() {
  7. stackA = new java.util.Stack<Integer>();
  8. stackB = new java.util.Stack<Integer>();
  9. max_index = -1;
  10. }
  11. void EnQueue(int v) {
  12. stackB.push(v);
  13. if(v > max_index) {
  14. max_index = v;
  15. }
  16. }
  17. Integer DeQueue() {
  18. if(stackA.isEmpty()) {
  19. while(!stackB.isEmpty()) {
  20. stackA.push(stackB.pop());
  21. }
  22. }
  23. int peek = stackA.pop();
  24. if(peek == max_index) {
  25. max_index = LookMax();
  26. }
  27. return peek;
  28. }
  29. int Max() {
  30. return max_index;
  31. }
  32. int LookMax() {
  33. int maxA = -1;
  34. int maxB = -1;
  35. Enumeration<Integer> itemsA = stackA.elements();
  36. while(itemsA.hasMoreElements()) {
  37. if(itemsA.nextElement() > maxA) {
  38. maxA = itemsA.nextElement();
  39. }
  40. }
  41. if(!stackB.isEmpty()) {
  42. Enumeration<Integer> itemsB = stackB.elements();
  43. while(itemsB.hasMoreElements()) {
  44. if(itemsB.nextElement() > maxB) {
  45. maxB = itemsB.nextElement();
  46. }
  47. }
  48. }
  49. if(maxA > maxB)
  50. return maxA;
  51. else
  52. return maxB;
  53. }
  54. }



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/960687
推荐阅读
相关标签
  

闽ICP备14008679号