239.滑动窗口最大值
代码逻辑:
变量:构造一个双端队列 , 构建存储最大值的数组
边界情况:传进来的为空,两个都要判断
构造双端队列,存储最大值数组
遍历前三个:初始化双端队列,数组的前三个,按照规则入队
while条件:队列不为空,且队尾元素 小于 数组当前值
while执行:移除队尾元素
将数组当前值加到队尾
结果的第一个存放队头 元素
循环:让滑动窗口滑动,进行相关规则的入队出队操作,其中每判断一次,存一次结果
1.判断:滑动窗口滑出去的元素 是否在队首 ---- 如果在,从队头移除
2. while条件:队列不为空,且队尾元素 小于 数组当前值
while执行:移除队尾元素
3.将当前数组值加入队尾
结果存储队头元素
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 0 || k == 0 ) return new int[0];
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[nums.length - k + 1];
for(int i = 0 ; i < k ; i++){
while( !deque.isEmpty() && deque.peekLast() < nums[i]){
deque.removeLast();
}
deque.addLast(nums[i]);
}
res[0] = deque.peekFirst();
for(int i = k ; i < nums.length ; i++){
if(deque.peekFirst() == nums[i - k]){
deque.removeFirst();
}
while( !deque.isEmpty() && deque.peekLast() < nums[i]){
deque.removeLast();
}
deque.addLast(nums[i]);
res[i - k + 1] = deque.peekFirst();
}
return res;
}
}
42.接雨水
一个凹槽是由三个柱子围成的 ---- 边界条件 --- 只有两个元素是构不成凹槽的
变量:栈(用来存储对应的柱子的下标 --- 不是存高度),结果值
遍历数组:
三种情况:栈空 --- 直接压栈 ,当前高度小于等于栈顶元素高度 --- 直接压栈
当前高度高于栈顶元素高度 --- 可以进行计算凹槽的标志
当前栈顶元素 为 凹槽底部
while条件:栈不空 ,且当前高度 大于 栈顶元素 --- 一直有凹槽存在,一直弹出
while执行:高度为当前高度 和 栈顶元素 高度的最小值, 减去凹槽底部高度
宽度为当前下标值 减去 栈顶元素 的下标值 减一
结果累加面积
class Solution {
public int trap(int[] height) {
if(height.length <= 2) return 0;
Stack<Integer> stack = new Stack<Integer>();
int res = 0;
for(int i = 0 ; i < height.length ; i++){
if(stack.isEmpty()){
stack.push(i);
} else if (height[i] <= height[stack.peek()]){
stack.push(i);
} else {
while(!stack.isEmpty() && height[i] > height[stack.peek()]){
int bottom = stack.peek();
stack.pop();
if(!stack.isEmpty()){
int h = Math.min(height[i],height[stack.peek()]) - height[bottom];
int w = i - stack.peek() - 1;
res += h * w;
}
}
stack.push(i);
}
}
return res;
}
}
少一层判断
while当前高度高于栈顶元素高度 --- 可以进行计算凹槽的标志
获取bottom
if 栈不空
获取高和宽,计算面积
641.设计循环双端队列
就是循环队列的理论实现
class MyCircularDeque {
private int capacity ;
private int front;
private int rear;
private int[] arr;
public MyCircularDeque(int k) {
capacity = k + 1;
arr = new int[capacity];
front = 0;
rear = 0;
}
public boolean insertFront(int value) {
if(isFull()){
return false;
}
front = ( front - 1 + capacity) % capacity;
arr[front] = value;
return true;
}
public boolean insertLast(int value) {
if(isFull()){
return false;
}
arr[rear] = value;
rear = ( rear + 1 ) % capacity;
return true;
}
public boolean deleteFront() {
if(isEmpty()){
return false;
}
front = ( front + 1 ) % capacity;
return true;
}
public boolean deleteLast() {
if(isEmpty()){
return false;
}
rear = ( rear - 1 + capacity ) % capacity;
return true;
}
public int getFront() {
if(isEmpty()){
return -1;
}
return arr[front];
}
public int getRear() {
if(isEmpty()){
return -1;
}
return arr[(rear - 1 + capacity) % capacity];
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return ( rear + 1 ) % capacity == front;
}
}
这两的添加顺序是不同的,所以后来得到的元素有问题;
85.最大矩形
演变于 84.柱状图中最大的矩形
是其 的二维画
最大值 ---- Math.max()
每一行转化为高度值
代码逻辑:
变量:设置高度数组 --- 长度为列数, 最大值
遍历每行每列,如果是1 ,则高度矩阵加1
复用84题代码
class Solution {
public int maximalRectangle(char[][] matrix) {
int[] heights = new int[matrix[0].length];
int maxArea = 0;
for(int row = 0 ; row < matrix.length ; row++){
for(int col = 0 ; col < matrix[0].length ; col++){
if(matrix[row][col] == '1'){
heights[col] += 1;
} else {
heights[col] = 0;
}
}
maxArea = Math.max(maxArea,largestRectangleArea(heights));
}
return maxArea;
}
public int largestRectangleArea(int[] heights) {
int res = 0;
Stack<Integer> stack = new Stack<Integer>();
int[] newHeight = new int[heights.length + 2];
newHeight[0] = 0;
newHeight[newHeight.length - 1] = 0;
for(int i = 1; i < heights.length + 1 ; i++){
newHeight[i] = heights[i - 1];
}
for(int i = 0 ; i < newHeight.length; i++){
while(!stack.isEmpty() && newHeight[i] < newHeight[stack.peek()]){
int cur = stack.pop();
int curHeight = newHeight[cur];
int leftIndex = stack.peek();
int rightIndex = i;
int curWidth = rightIndex - leftIndex - 1;
res = Math.max(res, curHeight * curWidth);
}
stack.push(i);
}
return res;
}
}