1. 队列
1.1 设计循环双端队列(641)
双向链表
class MyCircularDeque {private int capacity;private int size;private Node head;private Node tail;public MyCircularDeque(int k) {capacity = k;size = 0;head = new Node(-1, null, null);tail = new Node(-2, head, null);head.next = tail;}public boolean insertFront(int value) {if ( size >= capacity ) {return false;}size++;Node temp = head.next;head.next = new Node(value, head, temp);temp.prev = head.next;return true;}public boolean insertLast(int value) {if ( size >= capacity ) {return false;}size++;Node last = tail.prev;last.next = new Node(value, last, tail);tail.prev = last.next;return true;}public boolean deleteFront() {if (size == 0) {return false;}size--;Node temp = head.next.next;head.next = head.next.next;temp.prev = head;return true;}public boolean deleteLast() {if (size == 0) {return false;}size--;Node temp = tail.prev.prev;temp.next = temp.next.next;tail.prev = temp;return true;}public int getFront() {if (size == 0) {return -1;}Node temp = head.next;return temp.value;}public int getRear() {if (size == 0) {return -1;}Node temp = tail.prev;return temp.value;}public boolean isEmpty() {return size == 0;}public boolean isFull() {return size == capacity;}private static class Node {int value;Node prev;Node next;public Node(int value, Node prev, Node next) {this.value = value;this.prev = prev;this.next = next;}}}
数组: ```java
public class MyCircularDeque {
// 1、不用设计成动态数组,使用静态数组即可// 2、设计 head 和 tail 指针变量// 3、head == tail 成立的时候表示队列为空// 4、tail + 1 == head 表示为满// 5、注意做减法指针可能变成负数 可以用 (tail - 1 + capacity ) % capacity 来做tail移位private final int capacity;private final int[] arr;private int head;private int tail;public MyCircularDeque(int k) {// 多存一个用于区分队列满和空的情况capacity = k + 1;arr = new int[capacity];head = 0;tail = 0;}public boolean insertFront(int value) {if (isFull()) {return false;}head = (head - 1 + capacity) % capacity;arr[head] = value;return true;}public boolean insertLast(int value) {if (isFull()) {return false;}arr[tail] = value;tail = (tail + 1) % capacity;return true;}public boolean deleteFront() {if (isEmpty()) {return false;}// front 被设计在数组的开头,所以是 +1head = (head + 1) % capacity;return true;}public boolean deleteLast() {if (isEmpty()) {return false;}// rear 被设计在数组的末尾,所以是 -1tail = (tail - 1 + capacity) % capacity;return true;}public int getFront() {if (isEmpty()) {return -1;}return arr[head];}public int getRear() {if (isEmpty()) {return -1;}// 当 tail 为 0 时防止数组越界才加的capacityreturn arr[(tail - 1 + capacity) % capacity];}public boolean isEmpty() {return head == tail;}public boolean isFull() {// 注意:这个设计是非常经典的做法return (tail + 1) % capacity == head;}
}
<a name="qF8oM"></a>### 1.2 滑动窗口最大值(239)- 直接循环O(n^2)```javapublic int[] maxSlidingWindow(int[] nums, int k) {int[] resultArr = new int[nums.length - k + 1];for (int i = 0; i < nums.length - k + 1; i++) {int max = nums[i];for (int j = i; j < i + k; j++) {max = Math.max(max, nums[j]);}resultArr[i] = max;}return resultArr;}
-
1.3 层次遍历二叉树(102)
-
2. 栈
2.1 最小栈(155)
class MinStack {Deque<Integer> stack;Deque<Integer> minStack;public MinStack() {stack = new LinkedList<Integer>();minStack = new LinkedList<Integer>();minStack.push(Integer.MAX_VALUE);}public void push(int x) {stack.push(x);minStack.push(Math.min(minStack.peek(), x));}public void pop() {stack.pop();minStack.pop();}public int top() {return stack.peek();}public int getMin() {return minStack.peek();}}
2.2 删除链表第N个元素
解法一:栈,pop出 n+1个元素
public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode(0, head);ListNode temp = dummyHead;Stack<ListNode> stack = new Stack<>();while (null != temp) {stack.push(temp);temp = temp.next;}ListNode prev = stack.pop();for (int i = 0; i < n; i++) {prev = stack.pop();}if (prev.next != null) {prev.next = prev.next.next;}return dummyHead.next;}
-
2.3 有效括号(20)
解法一:用栈
public boolean isValid(String s) {if (s.length() % 2 == 1) {return false;}Map<Character, Character> map = new HashMap<>();map.put('(', ')');map.put('[', ']');map.put('{', '}');Stack<Character> stack = new Stack<>();char[] charArr = s.toCharArray();for (char c : charArr) {if (map.containsKey(c)) {stack.push(c);continue;}if (stack.isEmpty()) {return false;}Character temp = stack.pop();if (!map.get(temp).equals(c)) {return false;}}return stack.isEmpty();}
2.4 接雨水(42)hard
解法一:栈 ```java public int trap(int[] height) {
Deque<Integer> stack = new LinkedList<Integer>();int result = 0;for (int i = 0; i < height.length; ++i) {while (!stack.isEmpty() && height[i] > height[stack.peek()]) {int top = stack.pop();if (stack.isEmpty()) {break;}int left = stack.peek();int widthTemp = i - left - 1;int heightTemp = Math.min(height[left], height[i]) - height[top];result += widthTemp * heightTemp;}stack.push(i);}return result;
}
```
单调栈关注一下
序号 题目 题解
42. 接雨水(困难) 暴力解法、优化、双指针、单调栈
739. 每日温度(中等) 暴力解法 + 单调栈
496. 下一个更大元素 I(简单) 暴力解法、单调栈
316. 去除重复字母(困难) 栈 + 哨兵技巧(Java、C++、Python)
901. 股票价格跨度(中等) 「力扣」第 901 题:股票价格跨度(单调栈)
402. 移掉K位数字
581. 最短无序连续子数组
