栈:先进后出的线性表
    队列:先进先出的线性表
    截屏2020-07-11 上午10.31.47.png
    Leecode 225: 队列实现栈:采用Deque(或者使用LinkedList):含有的方法

    boolean **[add](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#add-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)将指定的元素追加到此列表的末尾。
    void **[add](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#add-int-E-)**(int index, [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) element)在此列表中的指定位置插入指定的元素。
    boolean **[addAll](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#addAll-java.util.Collection-)**([Collection](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Collection.html)<? extends [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html)> c)按照指定集合的迭代器返回的顺序将指定集合中的所有元素追加到此列表的末尾。
    boolean **[addAll](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#addAll-int-java.util.Collection-)**(int index, [Collection](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Collection.html)<? extends [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html)> c)将指定集合中的所有元素插入到此列表中,从指定的位置开始。
    void **[addFirst](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#addFirst-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)在该列表开头插入指定的元素。
    void **[addLast](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#addLast-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)将指定的元素追加到此列表的末尾。
    void **[clear](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#clear--)**()从列表中删除所有元素。
    [Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) **[clone](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#clone--)**()返回此 LinkedList的浅版本。
    boolean **[contains](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#contains-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)如果此列表包含指定的元素,则返回 true
    [Iterator](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Iterator.html)<[E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html)> **[descendingIterator](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#descendingIterator--)**()以相反的顺序返回此deque中的元素的迭代器。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[element](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#element--)**()检索但不删除此列表的头(第一个元素)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[get](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#get-int-)**(int index)返回此列表中指定位置的元素。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[getFirst](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#getFirst--)**()返回此列表中的第一个元素。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[getLast](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#getLast--)**()返回此列表中的最后一个元素。
    int **[indexOf](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#indexOf-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
    int **[lastIndexOf](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#lastIndexOf-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
    [ListIterator](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/ListIterator.html)<[E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html)> **[listIterator](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#listIterator-int-)**(int index)从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。
    boolean **[offer](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#offer-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)将指定的元素添加为此列表的尾部(最后一个元素)。
    boolean **[offerFirst](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#offerFirst-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)在此列表的前面插入指定的元素。
    boolean **[offerLast](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#offerLast-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)在该列表的末尾插入指定的元素。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[peek](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#peek--)**()检索但不删除此列表的头(第一个元素)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[peekFirst](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#peekFirst--)**()检索但不删除此列表的第一个元素,如果此列表为空,则返回 null
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[peekLast](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#peekLast--)**()检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[poll](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#poll--)**()检索并删除此列表的头(第一个元素)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[pollFirst](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#pollFirst--)**()检索并删除此列表的第一个元素,如果此列表为空,则返回 null
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[pollLast](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#pollLast--)**()检索并删除此列表的最后一个元素,如果此列表为空,则返回 null
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[pop](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#pop--)**()从此列表表示的堆栈中弹出一个元素。
    void **[push](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#push-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) e)将元素推送到由此列表表示的堆栈上。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[remove](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#remove--)**()检索并删除此列表的头(第一个元素)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[remove](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#remove-int-)**(int index)删除该列表中指定位置的元素。
    boolean **[remove](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#remove-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)从列表中删除指定元素的第一个出现(如果存在)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[removeFirst](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#removeFirst--)**()从此列表中删除并返回第一个元素。
    boolean **[removeFirstOccurrence](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#removeFirstOccurrence-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)删除此列表中指定元素的第一个出现(从头到尾遍历列表时)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[removeLast](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#removeLast--)**()从此列表中删除并返回最后一个元素。
    boolean **[removeLastOccurrence](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#removeLastOccurrence-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)删除此列表中指定元素的最后一次出现(从头到尾遍历列表时)。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) **[set](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#set-int-E-)**(int index, [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html) element)用指定的元素替换此列表中指定位置的元素。
    int **[size](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#size--)**()返回此列表中的元素数。
    [Spliterator](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Spliterator.html)<[E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html)> **[spliterator](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#spliterator--)**()在此列表中的元素上创建late-binding故障快速 Spliterator
    [Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html)[] **[toArray](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#toArray--)**()以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
    <T> T[] **[toArray](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/LinkedList.html#toArray-T:A-)**(T[] a)以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。

    实现:

    1. /**
    2. 采用双端队列:Deque实现,
    3. */
    4. class MyStack {
    5. private Deque<Integer> list;
    6. /** Initialize your data structure here. */
    7. public MyStack() {
    8. list = new LinkedList<Integer>();
    9. }
    10. /** Push element x onto stack. */
    11. public void push(int x) {
    12. list.add(x);
    13. }
    14. /** Removes the element on top of the stack and returns that element. */
    15. public int pop() {
    16. return list.pollLast();
    17. }
    18. /** Get the top element. */
    19. public int top() {
    20. return list.peekLast();
    21. }
    22. /** Returns whether the stack is empty. */
    23. public boolean empty() {
    24. return list.size()==0;
    25. }
    26. }
    27. /**
    28. * Your MyStack object will be instantiated and called as such:
    29. * MyStack obj = new MyStack();
    30. * obj.push(x);
    31. * int param_2 = obj.pop();
    32. * int param_3 = obj.top();
    33. * boolean param_4 = obj.empty();
    34. */

    Leetcode 232:栈实现队列:

    boolean **[empty](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html#empty--)**()测试此堆栈是否为空。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html) **[peek](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html#peek--)**()查看此堆栈顶部的对象,而不从堆栈中删除它。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html) **[pop](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html#pop--)**()删除此堆栈顶部的对象,并将该对象作为此函数的值返回。
    [E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html) **[push](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html#push-E-)**([E](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html) item)将项目推送到此堆栈的顶部。
    int **[search](http://www.matools.com/file/manual/jdk_api_1.8_google/java/util/Stack.html#search-java.lang.Object-)**([Object](http://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Object.html) o)返回一个对象在此堆栈上的基于1的位置。

    实现:利用栈实现队列必须使用两个栈,使用两个栈可以把原来栈先进后出变成先进先出

    1. class MyQueue {
    2. private Stack<Integer> stack1;
    3. private Stack<Integer> stack2;
    4. private Integer front;
    5. /** Initialize your data structure here. */
    6. public MyQueue() {
    7. stack1 = new Stack<>();
    8. stack2 = new Stack<>();
    9. }
    10. /** Push element x to the back of queue. */
    11. public void push(int x) {
    12. if(stack1.isEmpty()){
    13. front =x;
    14. }
    15. while(!stack1.isEmpty()){
    16. stack2.push(stack1.pop());
    17. }
    18. stack2.push(x);
    19. while(!stack2.isEmpty()){
    20. stack1.push(stack2.pop());
    21. }
    22. }
    23. /** Removes the element from in front of queue and returns that element. */
    24. public int pop() {
    25. return stack1.pop();
    26. }
    27. /** Get the front element. */
    28. public int peek() {
    29. if(!stack1.isEmpty())front =stack1.peek();
    30. return front;
    31. }
    32. /** Returns whether the queue is empty. */
    33. public boolean empty() {
    34. return stack1.isEmpty();
    35. }
    36. }
    37. /**
    38. * Your MyQueue object will be instantiated and called as such:
    39. * MyQueue obj = new MyQueue();
    40. * obj.push(x);
    41. * int param_2 = obj.pop();
    42. * int param_3 = obj.peek();
    43. * boolean param_4 = obj.empty();
    44. */

    Leetcode 155:最小栈

    1. // class MinStack {
    2. // private Stack <Integer> dataStack ;//数据栈
    3. // private Stack <Integer> minStack;//最小值栈
    4. // //private int min=0;//用于记录最小值;
    5. // // private int subMin =0; //用于记录上一个最小值
    6. // /** initialize your data structure here. */
    7. // public MinStack() {
    8. // dataStack =new Stack<Integer>();
    9. // minStack = new Stack<Integer>();
    10. // }
    11. // public void push(int x) {
    12. // dataStack.push(x);
    13. // if(minStack.isEmpty()){
    14. // minStack.push(x);
    15. // }else{
    16. // if(x<minStack.peek()){
    17. // minStack.push(x);
    18. // }else{
    19. // minStack.push(minStack.peek());
    20. // }
    21. // }
    22. // }
    23. // //同时弹出
    24. // public void pop() {
    25. // dataStack.pop();
    26. // minStack.pop();
    27. // }
    28. // public int top() {
    29. // return dataStack.peek();
    30. // }
    31. // public int getMin() {
    32. // return minStack.peek();
    33. // }
    34. // }
    35. //优化后结果
    36. // class MinStack {
    37. // private Stack <Integer> dataStack ;//数据栈
    38. // private Stack <Integer> minStack;//最小值栈
    39. // //private int min=0;//用于记录最小值;
    40. // // private int subMin =0; //用于记录上一个最小值
    41. // /** initialize your data structure here. */
    42. // public MinStack() {
    43. // dataStack =new Stack<Integer>();
    44. // minStack = new Stack<Integer>();
    45. // }
    46. // public void push(int x) {
    47. // dataStack.push(x);
    48. // if(minStack.isEmpty()||x<=minStack.peek()){
    49. // minStack.push(x);
    50. // }
    51. // }
    52. // public void pop() {
    53. // if(dataStack.pop().equals(minStack.peek()))
    54. // minStack.pop();
    55. // }
    56. // public int top() {
    57. // return dataStack.peek();
    58. // }
    59. // public int getMin() {
    60. // return minStack.peek();
    61. // }
    62. // }
    63. //采用Node实现
    64. class MinStack {
    65. private Stack<Node> stack;
    66. //private int min=0;//用于记录最小值;
    67. // private int subMin =0; //用于记录上一个最小值
    68. /** initialize your data structure here. */
    69. public MinStack() {
    70. stack =new Stack<>();
    71. }
    72. public void push(int x) {
    73. if(stack.isEmpty())
    74. stack.push(new Node(x,x));
    75. else
    76. stack.push(new Node(x,Math.min(stack.peek().min,x)));
    77. }
    78. public void pop() {
    79. stack.pop();
    80. }
    81. public int top() {
    82. return stack.peek().val;
    83. }
    84. public int getMin() {
    85. return stack.peek().min;
    86. }
    87. class Node{
    88. int min;
    89. int val;
    90. public Node(int val,int min){
    91. this.val =val;
    92. this.min =min;
    93. }
    94. }
    95. }
    96. /**
    97. * Your MinStack object will be instantiated and called as such:
    98. * MinStack obj = new MinStack();
    99. * obj.push(x);
    100. * obj.pop();
    101. * int param_3 = obj.top();
    102. * int param_4 = obj.getMin();
    103. */
    104. //一个栈完成,当即将压入的值小于记录的min最小值,先把当前最小值压入,然后再压入当前值,当弹出的最小值等于最小
    105. 小值时,先弹出,然后把最小值赋值为下一个即将弹出的值(第二小);
    106. class MinStack {
    107. private Stack<Integer> stack;
    108. private int min = Integer.MAX_VALUE;//记录当前最小值
    109. public MinStack() {
    110. stack =new Stack<>();
    111. }
    112. public void push(int x) {
    113. if(x<=min){
    114. stack.push(min);//如果压入的值比当前最小值还小,先把当前最小压入栈,然后再压入该值
    115. min =x;//最小值改变
    116. }
    117. stack.push(x);//压入当前值
    118. }
    119. public void pop() {
    120. if(stack.pop()==min){
    121. min =stack.pop();
    122. }
    123. }
    124. public int top() {
    125. return stack.peek();
    126. }
    127. public int getMin() {
    128. return min;
    129. }
    130. }

    Leetcode 946:验证栈序列:
    思路:借助辅助栈:将pushed数组压入栈,如果栈顶数组等于poped数组中poped[index],index是验证两者通过的个数,则将栈顶数组推出

    class Solution {
        public boolean validateStackSequences(int[] pushed, int[] popped) {
         Stack<Integer> stack = new Stack<Integer>();
         int j =0;//两个数组记录符合入栈出栈的数目
         for(int x: pushed){
             stack.push(x);
             while(!stack.isEmpty()&&j<pushed.length&&stack.peek()==popped[j]){
                 stack.pop();
                 j++;
             }
         }
         return j==pushed.length;//全部符合为True
        }
    }
    

    Leetcode:215:数组中第k大的:
    优先队列的思路是很朴素的。因为第 K 大元素,其实就是整个数组排序以后后半部分最小的那个元素。因此,我们可以维护一个有 K 个元素的最小堆:

    1、如果当前堆不满,直接添加;

    2、堆满的时候,如果新读到的数小于等于堆顶,肯定不是我们要找的元素,只有新都到的数大于堆顶的时候,才将堆顶拿出,然后放入新读到的数,进而让堆自己去调整内部结构。

    说明:这里最合适的操作其实是 replace,即直接把新读进来的元素放在堆顶,然后执行下沉(siftDown)操作。Java 当中的 PriorityQueue 没有提供这个操作,只好先 poll() 再 offer()。

    优先队列的写法就很多了,这里例举一下我能想到的(以下的写法大同小异,没有本质差别)。

    假设数组有 len 个元素。

    思路1:把 len 个元素都放入一个最小堆中,然后再 pop() 出 len - k 个元素,此时最小堆只剩下 k 个元素,堆顶元素就是数组中的第 k 个最大元素。

    思路2:把 len 个元素都放入一个最大堆中,然后再 pop() 出 k - 1 个元素,因为前 k - 1 大的元素都被弹出了,此时最大堆的堆顶元素就是数组中的第 k 个最大元素。

    import java.util.PriorityQueue;
    
    public class Solution {
    
        // 根据 k 的不同,选最大堆和最小堆,目的是让堆中的元素更小
        // 思路 1:k 要是更靠近 0 的话,此时 k 是一个较大的数,用最大堆
        // 例如在一个有 6 个元素的数组里找第 5 大的元素
        // 思路 2:k 要是更靠近 len 的话,用最小堆
    
        // 所以分界点就是 k = len - k
    
        public int findKthLargest(int[] nums, int k) {
            int len = nums.length;
            if (k <= len - k) {
                // System.out.println("使用最小堆");
                // 特例:k = 1,用容量为 k 的最小堆
                // 使用一个含有 k 个元素的最小堆
                PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a, b) -> a - b);
                for (int i = 0; i < k; i++) {
                    minHeap.add(nums[i]);
                }
                for (int i = k; i < len; i++) {
                    // 看一眼,不拿出,因为有可能没有必要替换
                    Integer topEle = minHeap.peek();
                    // 只要当前遍历的元素比堆顶元素大,堆顶弹出,遍历的元素进去
                    if (nums[i] > topEle) {
                        minHeap.poll();
                        minHeap.add(nums[i]);
                    }
                }
                return minHeap.peek();
    
            } else {
                // System.out.println("使用最大堆");
                assert k > len - k;
                // 特例:k = 100,用容量为 len - k + 1 的最大堆
                int capacity = len - k + 1;
                PriorityQueue<Integer> maxHeap = new PriorityQueue<>(capacity, (a, b) -> b - a);
                for (int i = 0; i < capacity; i++) {
                    maxHeap.add(nums[i]);
                }
                for (int i = capacity; i < len; i++) {
                    // 看一眼,不拿出,因为有可能没有必要替换
                    Integer topEle = maxHeap.peek();
                    // 只要当前遍历的元素比堆顶元素大,堆顶弹出,遍历的元素进去
                    if (nums[i] < topEle) {
                        maxHeap.poll();
                        maxHeap.add(nums[i]);
                    }
                }
                return maxHeap.peek();
            }
        }
    }
    

    采用快排:

    // class Solution {
    //     public int findKthLargest(int[] nums, int k) {
    //   //优化:当k较小的时候使用最小堆,k较大的时候较大的时候采用最大堆
    //   int len = nums.length;
    //    if(k<=len-k){//采用最小堆,lamda表达式实现Comparable接口:默认最小堆
    //     PriorityQueue<Integer> pq = new PriorityQueue<Integer>(k,(a,b)->a-b);
    //     for(int num:nums){
    //         if(pq.size()<k){
    //             pq.add(num);
    //         }else{
    //             if(num>pq.peek()){
    //             pq.poll();
    //             pq.add(num);
    //             }
    //         }
    //     }
    //     return pq.peek();
    //     }else{
    //         int capacity = len-k+1;
    //         PriorityQueue<Integer>pq_max =new PriorityQueue<>(capacity,(a,b)->b-a);
    //         for(int num:nums){
    //             if(pq_max.size()<capacity){
    //                 pq_max.add(num);
    //             }else{
    //                 if(num<pq_max.peek()){
    //                     pq_max.poll();
    //                     pq_max.add(num);
    //                 }
    //             }
    //         }
    //         return pq_max.peek();
    //     }
    
    //     }
    // }
    public class Solution {
    
        public int findKthLargest(int[] nums, int k) {
            int len = nums.length;
            int left = 0;
            int right = len - 1;
    
            // 转换一下,第 k 大元素的索引是 len - k
            int target = len - k;
          //  if(len==1) return nums[len-1];
    
          //如果是快速排序则需要index前后都需要排
            while (true) {
                int index = partition(nums, left, right);
                if (index == target) {
                    return nums[index];
                    //index小于目标,直接从index右边进行切分
                } else if (index < target) {
                    left = index + 1;
                } else {
                    //大于目标,从index左边进行切分
                    right = index - 1;
                }
            }
        }
    
        /**
         * 在数组 nums 的子区间 [left, right] 执行 partition 操作,返回 nums[left] 排序以后应该在的位置
         * 在遍历过程中保持循环不变量的语义
         * 1、[left + 1, j] < nums[left]
         * 2、(j, i] >= nums[left]
         *
         * @param nums
         * @param left
         * @param right
         * @return
         */
         public int partition(int[] nums, int left, int right) {
        //     int pivot = nums[left];
        //     int j =left;
        //     for (int i = left + 1; i <= right; i++) {
        //         if (nums[i] < pivot) {
        //             // 小于 pivot 的元素都被交换到前面
        //             j++;
        //             swap(nums, j, i);
        //         }
        //     }
        //     // 在之前遍历的过程中,满足 [left + 1, j] < pivot,并且 (j, i] >= pivot
        //     swap(nums, j, left);
        //     // 交换以后 [left, j - 1] < pivot, nums[j] = pivot, [j + 1, right] >= pivot
        //     return j;
            /**************快速排序完整版************/
        //      int i = left;
        //    int j = right;
        //    int vo = nums[left];
        //    while (i < j) {
        //        //从右边开始
        //        while (vo <=nums[j]&&i<j) {
        //            j--;
        //        }
        //        //从左边开始
        //        while (vo >= nums[i]&&i<j) {
        //            i++;
        //        }
        //        //如果找到了
        //        if (i < j) {
        //            swap(nums, i, j);
    
        //        }
        //    }
        //    //调整首位置元素到准确位置
        //    swap(nums,left,j);
        //    //返回准备位置作为切分位置
        //    return j;
        /**完整快速排序方法**/
         int i =left;
            int j =right+1;
            int vo =nums[left];
            while(true){
                while(i<right&&nums[++i]<vo);
                while(j>left&&vo<nums[--j]);
                if(i>=j)break;
                swap(nums,i,j);
            }
            swap(nums,left,j);
            return j;
    
        }
    
        private void swap(int[] nums, int index1, int index2) {
            int temp = nums[index1];
            nums[index1] = nums[index2];
            nums[index2] = temp;
        }
    }
    

    Leetcode:295 数据流的中位数 采用大顶锥和小顶锥结合方式

    class MedianFinder {
        //采用大小堆组合
        /** initialize your data structure here. */
        PriorityQueue<Integer> maxPQ ;
        PriorityQueue<Integer> minPQ;
        //初始化
        public MedianFinder() {
         maxPQ = new PriorityQueue<>((a,b)->b-a);
         minPQ = new PriorityQueue<>();
        }
        //保证大顶锥比小顶锥多1
        public void addNum(int num) {
         maxPQ.offer(num);
         minPQ.offer(maxPQ.poll());
         if(maxPQ.size()<minPQ.size()){
             maxPQ.offer(minPQ.poll());
         }
        }
    
        public double findMedian() {
        if(minPQ.size()<maxPQ.size()){
            return maxPQ.peek();
        }
        else{
            return (double) (maxPQ.peek()+minPQ.peek())/2;
        }
        }
    }
    
    /**
     * Your MedianFinder object will be instantiated and called as such:
     * MedianFinder obj = new MedianFinder();
     * obj.addNum(num);
     * double param_2 = obj.findMedian();
     */