简单粗暴,记录备战过程,持续更新
单调栈
是栈的一种类型,但是有些自己的特性; 特性如下:
- 要求栈中的元素是单调递增或者单调递减
pop时元素是递增,即单调递增栈,pop时元素是递减,即单调递减栈
示例:栈内元素(左栈底,右栈顶),[1,2,3,4], 出栈后4,3,2,1, 即单调递增栈;
适用场景
使用单调栈场景是求解下一个大于 xxx或者下一个小于 xxx这种题目。所有当你有这种需求的时候,就应该想到单调栈。
实战
实战1,leetcode 84. 柱状图中最大的矩形
public class Lee0084 {
public static void main(String[] args) {
int[] arr = {2, 3, 5, 6, 1};
System.out.println(largestRectangleArea(arr));
}
public static int largestRectangleArea(int[] heights) {
int ans = 0;
Deque<Integer> stack = new ArrayDeque<>();
// 增加哨兵节点
int[] tmpHeights = new int[heights.length + 1];
for (int i = 0, len = heights.length; i < len; i++) {
tmpHeights[i] = heights[i];
}
tmpHeights[heights.length] = 0;
heights = tmpHeights;
stack.addLast(-1);
for (int i = 0, len = heights.length; i < len; i++) {
// 空 或 大于栈顶,进栈
if (stack.getLast() == -1 || heights[stack.getLast()] < heights[i]) {
stack.addLast(i);
}
// 小于等于,出栈
else {
while ((stack.getLast() > -1 && heights[stack.getLast()] >= heights[i])) {
// 高 乘 宽(右非大于下标 - 左非大于下标 - 1)
int temp = heights[stack.removeLast()] * (i - stack.getLast() - 1);
ans = Math.max(ans, temp);
}
stack.addLast(i);
}
}
return ans;
}
}
实战2,leetcode 42.接雨水
public class Lee0042 {
public static void main(String[] args) {
int[] arr = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
System.out.println(trap(arr));
}
public static int trap(int[] height) {
int sum = 0;
Deque<Integer> stack = new ArrayDeque<>();
for (int i = 0, len = height.length; i < len; i++) {
// 大于,出栈
while (!stack.isEmpty() && height[stack.getLast()] < height[i]) {
int topHeight = stack.removeLast();
if (stack.isEmpty()) {
break;
}
int distance = i - stack.getLast() - 1;
sum += distance * (Math.min(height[i], height[stack.getLast()]) - height[topHeight]);
}
stack.addLast(i);
}
return sum;
}
}
实战3,leetcode 496. 下一个更大元素 I
import java.util.*;
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Map<Integer,Integer> map = new HashMap<>();
Deque<Integer> stack = new ArrayDeque<>();
for(int i = 0,len = nums2.length ; i< len ; i++){
while(!stack.isEmpty() && stack.getLast() < nums2[i]){
map.put( stack.removeLast(),nums2[i]);
}
stack.addLast(nums2[i]);
}
for(int i = 0, len = nums1.length ; i< len ; i++){
nums1[i] = map.getOrDefault(nums1[i],-1);
}
return nums1;
}
}
实战4,leetcode, 739. 每日温度
import java.util.*;
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
Deque<Integer> stack = new ArrayDeque<>();
for(int i = 0 ; i < temperatures.length ; i++){
while(!stack.isEmpty() && temperatures[stack.getLast()] < temperatures[i]){
temperatures[stack.getLast()] = i - stack.removeLast();
}
stack.addLast(i);
}
while(!stack.isEmpty()){
temperatures[stack.removeLast()] = 0;
}
return temperatures;
}
}
实战5,leetcode 316. 去除重复字母
import java.util.*;
class Solution {
public String removeDuplicateLetters(String s) {
int [] lastIndex = new int[26];
char[] charArr = s.toCharArray();
for(int i= 0 ; i < charArr.length ; i++){
lastIndex[charArr[i]-'a'] = i;
}
Boolean[] inStack = new Boolean[26];
Deque<Character> stack = new ArrayDeque<>();
for(int i= 0; i < charArr.length ; i++){
// 栈顶 > 当前 , 且后面还有, 则出栈
while( !stack.isEmpty() && stack.getLast() > charArr[i] && i < lastIndex[stack.getLast() - 'a']){
inStack[stack.getLast() - 'a'] = false;
stack.removeLast();
}
// 空
inStack[charArr[i] - 'a'] = true;
stack.addLast(charArr[i]);
}
StringBuilder ret = new StringBuilder();
while(!stack.isEmpty() ){
ret.append(stack.removeFirst());
}
return ret.toString();
}
}
实战6 155. 最小栈
class MinStack {
private Deque deque ;
private Queue priorityQueue ;
public MinStack() {
deque = new ArrayDeque<Integer>();
priorityQueue = new PriorityQueue<Integer>();
}
public void push(int val) {
deque.addLast(val);
priorityQueue.add(val);
}
public void pop() {
int val = (Integer)deque.removeLast();
priorityQueue.remove(val);
}
public int top() {
return (Integer)deque.getLast();
}
public int getMin() {
return (Integer)priorityQueue.peek();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
实战7 503. 下一个更大元素 II
class Solution {
public int[] nextGreaterElements(int[] nums) {
int len = nums.length;
int[] ans = new int[len];
Arrays.fill(ans,-1);
ArrayDeque<Integer> stack = new ArrayDeque<>(len);
for(int i = 0 ; i < 2*len - 1 ; i++){
while(!stack.isEmpty() && nums[stack.getLast()] < nums[i % len]){
int val = stack.removeLast();
ans[val] = nums[i % len];
}
stack.addLast(i % len);
}
return ans;
}
}
实战8 20. 有效的括号
class Solution {
public boolean isValid(String s) {
int len = s.length();
ArrayDeque<Character> stack = new ArrayDeque<>(len);
for(int i = 0; i < len; i++){
if(stack.isEmpty()){
stack.addLast(s.charAt(i));
}else{
char tmp = stack.getLast();
if(tmp == '(' && s.charAt(i) == ')'){
stack.removeLast();
}else if (tmp == '{' && s.charAt(i) == '}'){
stack.removeLast();
}else if (tmp == '[' && s.charAt(i) == ']'){
stack.removeLast();
}else{
stack.addLast(s.charAt(i));
}
}
}
return stack.isEmpty() ? true : false;
}
}
实战9 71. 简化路径
class Solution {
public String simplifyPath(String path) {
String[] names = path.split("/");
ArrayDeque<String> stack = new ArrayDeque<>(names.length);
for(String name : names){
if("..".equals(name)){
if(!stack.isEmpty()){
stack.removeLast();
}
}else if(name.length() > 0 && !".".equals(name)){
stack.addLast(name);
}
}
StringBuilder sb = new StringBuilder();
if(stack.isEmpty()){
sb.append("/");
}
while(!stack.isEmpty()){
sb.append("/");
sb.append(stack.removeFirst());
}
return sb.toString();
}
}