NC刷题笔记4-栈

本博客文章(学习笔记)导航 (点击这里访问)
在这里插入图片描述

NC14 按之字形顺序打印二叉树

输入:
二叉树
   1
 2   3
   4   5
输出:
[[1],
[3,2],
[4,5]]
思路1:
	1 双端队列,用于存放二叉树结点信息
	2 用链表存储每层的信息,奇数从左到右,偶数从右向左
import java.util.  ;
/  
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}
  /
public class Solution {
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        LinkedList<TreeNode> queue=new LinkedList<TreeNode>();
        if(pRoot==null) return res;
        queue.add(pRoot);
        int index=0;
        while(!queue.isEmpty()){
            int n=queue.size();
            LinkedList<Integer> temp=new LinkedList<>();
            index++;
            for(int i=0;i<n;i++){
                TreeNode node=queue.poll();
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
                if(index%2==1){
                    temp.addLast(node.val);
                }else{
                    temp.addFirst(node.val);
                }
            }
            res.add(new ArrayList<>(temp));
        }
        return res;
    }

}

NC45 实现二叉树先序,中序和后序遍历

描述
给定一棵二叉树,分别按照二叉树先序,中序和后序打印所有的节点。

数据范围:0≤n≤1000,树上每个节点的val值满足0≤val≤100
要求:空间复杂度 O(n),时间复杂度 O(n)
示例1
输入:{1,2,3}
返回值:[[1,2,3],[2,1,3],[2,3,1]]

示例2
输入:{}
返回值:[[],[],[]]
思路1:递归写法
	根左右
	左根右
	左右根
思路2:非递归写法
	根左右
	左根右
	左右根
思路1import java.util.  ;

/  
    public class TreeNode {
      int val = 0;
      TreeNode left = null;
      TreeNode right = null;
    }
   /

public class Solution {
    /  
        
        @param root TreeNode类 the root of binary tree
        @return int整型二维数组
       /
    public int[][] threeOrders (TreeNode root) {
        // write code here
        ArrayList<Integer> res1=new ArrayList<>();
        ArrayList<Integer> res2=new ArrayList<>();
        ArrayList<Integer> res3=new ArrayList<>();
        preOrder(root,res1);
        inOrder(root,res2);
        postOrder(root,res3);
        return fillArray(res1,res2,res3);
    }
    
    public void preOrder(TreeNode root,ArrayList<Integer> res){
        if(root==null) return;
        res.add(root.val);
        if(root.left!=null) preOrder(root.left,res);
        if(root.right!=null) preOrder(root.right,res);
    }
    
    public void inOrder(TreeNode root,ArrayList<Integer> res){
        if(root==null) return;
        if(root.left!=null) inOrder(root.left,res);
        res.add(root.val);
        if(root.right!=null) inOrder(root.right,res);
    }
    
    public void postOrder(TreeNode root,ArrayList<Integer> res){
        if(root==null) return;
        if(root.left!=null) postOrder(root.left,res);
        if(root.right!=null) postOrder(root.right,res);
        res.add(root.val);
    }
    
    public int[][] fillArray(ArrayList<Integer> res1,ArrayList<Integer> res2,ArrayList<Integer> res3){
        int[][] res=new int[3][res1.size()];
        for(int i=0;i<res1.size();i++){
            res[0][i]=res1.get(i);
            res[1][i]=res2.get(i);
            res[2][i]=res3.get(i);
        }
        return res;
    }
}
思路2import java.util.  ;
public class Solution {
    public int[][] threeOrders (TreeNode root) {
        ArrayList<Integer> res1=new ArrayList<>();
        ArrayList<Integer> res2=new ArrayList<>();
        ArrayList<Integer> res3=new ArrayList<>();
        preOrder(root,res1);
        inOrder(root,res2);
        postOrder(root,res3);
        return fillArray(res1,res2,res3);
    }

    public void preOrder(TreeNode root, ArrayList<Integer> list) {
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode curr = stack.pop();
            list.add(curr.val);
            if (curr.right != null) {
                stack.push(curr.right);
            }
            if (curr.left != null) {
                stack.push(curr.left);
            }
        }
    }

    public void inOrder(TreeNode root, ArrayList<Integer> list) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curr = root;
        while (!stack.isEmpty() || curr != null) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                curr = stack.pop();
                list.add(curr.val);
                curr = curr.right;
            }
        }
    }

    public void postOrder(TreeNode root, ArrayList<Integer> list) {
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode curr = stack.pop();
            list.add(0, curr.val);
            if(curr.left != null) {
                stack.push(curr.left);
            }
            if(curr.right != null) {
                stack.push(curr.right);
            }
        }
    }

    public int[][] fillArray(ArrayList<Integer> res1,ArrayList<Integer> res2,ArrayList<Integer> res3){
        int[][] res=new int[3][res1.size()];
        for(int i=0;i<res1.size();i++){
            res[0][i]=res1.get(i);
            res[1][i]=res2.get(i);
            res[2][i]=res3.get(i);
        }
        return res;
    }
}

NC52 有效括号序列

描述
给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。
数据范围:字符串长度0≤n≤10000
要求:空间复杂度 O(n),时间复杂度 O(n)

示例1
输入:"["
返回值:false

示例2
输入:"[]"
返回值:true
思路1:
	模拟栈,最后stack为空就是有效,不为空就是无效
思路2:
	模拟栈,放入的时候不匹配就直接返回false
思路1import java.util.  ;
public class Solution {
    public boolean isValid (String s) {
        // write code here
        Stack<Character> stack=new Stack<>();
        char[] chars=s.toCharArray();
        for(int i=0;i<chars.length;i++){
            char c=chars[i];
            if(c==']'&&!stack.isEmpty()&&stack.peek()=='['){
                stack.pop();
            }else if(c==')'&&!stack.isEmpty()&&stack.peek()=='('){
                stack.pop();
            }else if(c=='}'&&!stack.isEmpty()&&stack.peek()=='{'){
                stack.pop();
            }else{
                stack.push(c);
            }
        }
        return stack.isEmpty()?true:false;
    }
}
思路2import java.util.  ;
public class Solution {
    public boolean isValid (String s) {
        // write code here
        Stack<Character> stack=new Stack<Character>();
        char[] chars=s.toCharArray();
        for(int i=0;i<chars.length;i++){
            char c=chars[i];
            if(c=='('||c=='['||c=='{'){
                 stack.push(c);
            }else if(c==')'){
                if(stack.isEmpty()) return false;
                if(stack.peek()!='(') return false;
                stack.pop();
            }else if(c==']'){
                if(stack.isEmpty()) return false;
                if(stack.peek()!='[') return false;
                stack.pop();
            }else if(c=='}'){
                if(stack.isEmpty()) return false;
                if(stack.peek()!='{') return false;
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}

NC76 用两个栈实现队列

思路1:
	一个栈负责进,一个栈负责出
import java.util.Stack;
public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    public void push(int node) {
        stack1.push(node);
    }
    public int pop() {
        if(!stack2.isEmpty()){
            return stack2.pop();
        }else{
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            return stack2.pop();
        }
    }
}

LC84 直方图最大矩阵

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积

例1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

例2:
输入: heights = [2,4]
输出: 4
思路:
	单调栈,找到左右比自己小的索引
	1 维护一个从小到大的单调栈
	2 新建数组长度比原来数组长度多2
	3 遍历新数组,开始单调栈构建,每碰到逆序的时候,弹出元素,弹出的元素作为高度,stack的顶部为左端,i为右端,计算一下面积,
class Solution {
    public int largestRectangleArea(int[] heights) {
        int res = 0;
        Deque<Integer> stack = new ArrayDeque<>();
        int[] new_heights = new int[heights.length + 2];
        for (int i = 1; i < heights.length + 1; i++) {
            new_heights[i] = heights[i - 1];
        }
        for (int i = 0; i < new_heights.length; i++) {
            while (!stack.isEmpty() && new_heights[stack.peek()] > new_heights[i]) {
                int cur = stack.pop();
                int l = stack.peek();
                int r = i;
                res = Math.max(res, (r - l - 1)    new_heights[cur]);
            }
            stack.push(i);
        }
        return res;
    }
}

NC90 包含min函数的栈

描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。

此栈包含的方法有:
push(value):将value压入栈中
pop():弹出栈顶元素
top():获取栈顶元素
min():获取栈中最小元素

数据范围:操作数量满足0≤n≤300  ,输入的元素满足∣val∣≤10000 
进阶:栈的各个操作的时间复杂度是O(1)  ,空间复杂度是O(n) 

示例:
输入:    ["PSH-1","PSH2","MIN","TOP","POP","PSH1","TOP","MIN"]
输出:    -1,2,1,-1
解析:
"PSH-1"表示将-1压入栈中,栈中元素为-1
"PSH2"表示将2压入栈中,栈中元素为2,-1
“MIN”表示获取此时栈中最小元素==>返回-1
"TOP"表示获取栈顶元素==>返回2
"POP"表示弹出栈顶元素,弹出2,栈中元素为-1
"PSH1"表示将1压入栈中,栈中元素为1,-1
"TOP"表示获取栈顶元素==>返回1
“MIN”表示获取此时栈中最小元素==>返回-1

示例1
输入:["PSH-1","PSH2","MIN","TOP","POP","PSH1","TOP","MIN"]
返回值:-1,2,1,-1
思路:
	维护两个栈,一个保存出入栈的顺序,一个保存最小元素
	最小栈:
		入栈:为空 或者 小于等于栈顶元素
		出栈:pop元素等于栈顶就pop
import java.util.Stack;
public class Solution {
    Stack<Integer> minstack=new Stack<>();
    Stack<Integer> stack=new Stack<>();
    public void push(int node) {
        stack.push(node);
        if(minstack.isEmpty()||(!minstack.isEmpty()&&minstack.peek()>=node)){
            minstack.push(node);
        }
    }
    public void pop() {
        int n=stack.pop();
        if(minstack.peek()==n){
            minstack.pop();
        }
    }
    public int top() {
        return stack.peek();
    }
    public int min() {
        return minstack.peek();
    }
}

NC115 栈和排序

描述
给你一个 1 到 n 的排列和一个栈,并按照排列顺序入栈
你要在不打乱入栈顺序的情况下,仅利用入栈和出栈两种操作,输出字典序最大的出栈序列
排列:指 1 到 n 每个数字出现且仅出现一次
数据范围:1≤n≤5×10^4,排列中的值都满足1≤val≤n
进阶:空间复杂度 O(n) ,时间复杂度 O(n)

示例1
输入:[2,1,5,3,4]
返回值:[5,4,3,1,2]
说明:
操作       栈     结果
2 入栈;[2]       []
1 入栈;[2\1]     []
5 入栈;[2\1\5]   []
5 出栈;[2\1]     [5]
3 入栈;[2\1\3]   [5]
4 入栈;[2\1\3\4] [5]
4 出栈;[2\1\3]   [5,4]
3 出栈;[2\1]     [5,4,3]
1 出栈;[2]       [5,4,3,1]
2 出栈;[]        [5,4,3,1,2]  

示例2
输入:[1,2,3,4,5]
返回值:[5,4,3,2,1]
思路:
	需要一个标记数组,因为元素是1-n,所以第一个出栈的就是n
	1 需要一个栈、一个标记数组
	2 入栈并标记 到n的第一个出栈
	3 比较栈顶元素和为入栈元素的最大值,谁大弹谁
import java.util.  ;
public class Solution {
    public int[] solve (int[] a) {
        Stack<Integer> stack=new Stack<>();
        int n=a.length;
        boolean[] status=new boolean[n+1];
        int[] res=new int[n];
        int count=0;
        for(int i=0;i<a.length;i++){
            stack.push(a[i]);
            status[a[i]]=true;
            while(n>0 &&status[n]){
                n--;
            }
            while(!stack.isEmpty() && n<=stack.peek()){
                res[count++]=stack.pop();
            }
        }
        while(!stack.isEmpty()){
            res[count++]=stack.pop();
        }
        return res;
    }
}

NC117 直方图最大矩阵

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积

例1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

例2:
输入: heights = [2,4]
输出: 4
思路:
	单调栈,找到左右比自己小的索引
	1 维护一个从小到大的单调栈
	2 新建数组长度比原来数组长度多2
	3 遍历新数组,开始单调栈构建,每碰到逆序的时候,弹出元素,弹出的元素作为高度,stack的顶部为左端,i为右端,计算一下面积,
class Solution {
    public int largestRectangleArea(int[] heights) {
        int res = 0;
        Deque<Integer> stack = new ArrayDeque<>();
        int[] new_heights = new int[heights.length + 2];
        for (int i = 1; i < heights.length + 1; i++) {
            new_heights[i] = heights[i - 1];
        }
        for (int i = 0; i < new_heights.length; i++) {
            while (!stack.isEmpty() && new_heights[stack.peek()] > new_heights[i]) {
                int cur = stack.pop();
                int l = stack.peek();
                int r = i;
                res = Math.max(res, (r - l - 1)    new_heights[cur]);
            }
            stack.push(i);
        }
        return res;
    }
}

NC137 表达式求值

描述
请写一个整数计算器,支持加减乘三种运算和括号。
数据范围:0≤∣s∣≤100,保证计算结果始终在整型范围内
要求:空间复杂度:O(n),时间复杂度O(n)

示例1
输入:"1+2"
返回值:3

示例2
输入:"(2  (3-4))  5"
返回值:-10

示例3
输入:"3+2  3  4-1"
返回值:26
思路:
	双栈(为了避免负数开头,数字栈中压入0)
	1 (和  直接入栈
	2 数字获取整个数字入栈
	3 +、-进行上一步的计算
	4 )把最近的括号计算完
	5 遍历完开始最后的合并计算,直到操作符栈为空
import java.util.Stack;
/  
    @Author 丁永新
    @Date 2022/1/23
   /
public class Solution {
    public int solve (String s) {
        s=s.replaceAll(" ","");//替换空格
        char[] chars=s.toCharArray();
        Stack<Integer> numops=new Stack<>();
        numops.add(0);//防止出现负数为第一个数字
        Stack<Character> signops=new Stack<>();
        for(int i=0;i<chars.length;i++){
            char c=chars[i];
            if(c=='('||c=='  '||c=='/'){
                signops.push(c);
            }else if(isNum(c)){
                String temp="";
                while(i<chars.length&&isNum(chars[i])){
                    temp+=chars[i];
                    i++;
                }
                i--;
                numops.push(Integer.parseInt(temp));
            }else if(c=='+'||c=='-'){
                while(!numops.isEmpty()&&!signops.isEmpty()
                      &&(signops.peek()=='+'||signops.peek()=='-'||signops.peek()=='  '||signops.peek()=='/')){
                    int n1=numops.pop();
                    int n2=numops.pop();
                    char sig=signops.pop();
                    numops.push(calculation(n2,n1,sig));
                }
                signops.push(c);
            }else if(c==')'){
                while(!numops.isEmpty()&&signops.peek()!='('){
                    int n1=numops.pop();
                    int n2=numops.pop();
                    char sig=signops.pop();
                    numops.push(calculation(n2,n1,sig));
                }
                signops.pop();
            }
        }
        while(!signops.isEmpty()){
            int n1=numops.pop();
            int n2=numops.pop();
            char sig=signops.pop();
            numops.push(calculation(n2,n1,sig));
        }

        return numops.peek();
    }

    public int calculation(int a,int b,char sign){
        switch(sign){
            case '+':return a+b;
            case '-':return a-b;
            case '  ':return a  b;
            case '/':return (int)(a/b);
            default :return 0;
        }
    }

    public boolean isNum(char c){
        if(c>='0'&&c<='9') return true;
        return false;
    }
}

NC 157单调栈

描述
给定一个长度为 n 的可能含有重复值的数组 arr ,找到每一个 i 位置左边和右边离 i 位置最近且值比 arri 小的位置。
请设计算法,返回一个二维数组,表示所有位置相应的信息。位置信息包括:两个数字 l 和 r,如果不存在,则值为 -1,下标从 0 开始。
数据范围:1≤n≤10^5 ,-10^9≤arr[i]≤10^9
进阶:空间复杂度 O(n) ,时间复杂度 O(n)

示例1
输入:[3,4,1,5,6,2,7]
返回值:[[-1,2],[0,2],[-1,-1],[2,5],[3,5],[2,-1],[5,-1]]

示例2
输入:[1,1,1,1]
返回值:[[-1,-1],[-1,-1],[-1,-1],[-1,-1]]
思路1:
	暴力解法:寻找位置index左右两侧第一个比index处小的索引
思路2:
	单调栈:单调栈一般用于求左右两边比当前值小或大的数据结构
	求左侧:
	[3,4,1,5,6,2,7]
	num=3 栈为空 -1 入栈  单调栈:0
	num=4 大于栈顶 0 符合  入栈  单调栈:0 1
	num=1 小于栈顶 -1 弹出所有 入栈 单调栈 2
	num=5 大于栈顶 2 符合 入栈  单调栈 2 3
	num=6 大于栈顶 3 符合 入栈 单调栈 2 3 4
	num=2 小于栈顶 2 不符合 弹出 3 4 入栈 单调栈 2 5
	num=7 大于栈顶 5 符合 入栈 单调栈 2 5 6
    左侧结果:-1 0 -1 2 3 2 5
    右侧结果:2 2 -1 5 5 -1 -1
思路1import java.util.  ;
public class Solution {
    public int[][] foundMonotoneStack (int[] nums) {
        // write code here
        int len = nums.length;
        int ans[][] = new int[len][2];
        for(int i=0;i<len;i++){
            int l=-1,r=-1;
            for(int j=i-1;j>=0;j--){
                if(nums[j]<nums[i]){
                    l = j;
                    break;
                }
            }
            for(int k=i+1;k<len;k++){
                if(nums[k]<nums[i]){
                    r = k;
                    break;
                }
            }
            ans[i][0] = l;
            ans[i][1] = r;
        }
        return ans;
    }
}
思路2import java.util.  ;
public class Solution {
    public int[][] foundMonotoneStack (int[] nums) {
        Stack<Integer> stack=new Stack<>();
        int[][] ans=new int[nums.length][2];
        //左侧单调栈
        for(int i=0;i<nums.length;i++){
            while(!stack.isEmpty()&&nums[stack.peek()]>=nums[i]){
                stack.pop();
            }
            if(stack.isEmpty()){
                ans[i][0]=-1;
            }else{
                ans[i][0]=stack.peek();
            }
            stack.push(i);
        }
        //右侧单调栈
        stack.clear();
        for(int i=nums.length-1;i>=0;i--){
            while(!stack.isEmpty()&&nums[stack.peek()]>=nums[i]){
                stack.pop();
            }
            if(stack.isEmpty()){
                ans[i][1]=-1;
            }else{
                ans[i][1]=stack.peek();
            }
            stack.push(i);
        }
        return ans;
    }
}

NC175 合法括号字符串

描述
给定一个字符串s,字符串s只包含以下三种字符: (,  ,),请你判断 s是不是一个合法的括号字符串。合法括号字符串有如下规则:
1.左括号'('必须有对应的右括号')'
2.右括号')'必须有对应的左括号'('
3.左括号必须在对应的右括号前面
4.  可以视为单个左括号,也可以视为单个右括号,或者视为一个空字符
5.空字符串也视为合法的括号字符串
数据范围: 1<=s.length<=100
示例1  输入:"()()"  返回值:true
示例2  输入:"((  )"  返回值:true
示例3  输入:"(  )"  返回值:true
思路1:
	模拟栈
	双栈 left star
	1 记录左括号下标和星号下表
	2 左括号、星号直接入栈
	3 右括号开始消去,优先消除左括号,在消除  号
	4 最后判断剩下的左括号和星号是否匹配
思路2:
	贪心算法:左括号最小应该消除几个能不能消完 右括号最小应该消除几个能不能消完
思路1import java.util.  ;
public class Solution {
    /  
        代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
        @param s string字符串 
        @return bool布尔型
       /
    public boolean isValidString (String s) {
        //新建两个栈left、star,分别记录未匹配的左括号和  号对应下标
        LinkedList<Integer> left=new LinkedList<>();
        LinkedList<Integer> star=new LinkedList<>();
        int n=s.length();
        for(int i=0;i<n;i++){
            char c=s.charAt(i);
            //左括号下标入栈
            if(c=='('){
                left.push(i);
            }
            //  号下标入栈
            else if(c=='  '){
                star.push(i);
            }
            //如果是右括号
            else{
                //首先匹配左括号
                if(!left.isEmpty()){
                    left.pop();
                }
                //其次匹配  号
                else if(!star.isEmpty()){
                    star.pop();
                }
                //如果都没有,说明有右括号找不到匹配对象
                else{
                    return false;
                }
            }
        }
        //检查未匹配的左括号和  号
        while(!left.isEmpty()&&!star.isEmpty()){
            int top1=left.pop();
            int top2=star.pop();
            //每一个左括号都必须有一个  号(视为右括号)与之匹配
            if(top1>top2){
                return false;
            }
        }
        return left.isEmpty();
    }
}
思路2import java.util.  ;
public class Solution {
    public boolean isValidString (String s) {
        int cnt=0;int n=s.length();
        for(int i=0;i<n;i++){
            if(s.charAt(i)==')'){
                if(cnt<1) return false;
                cnt--;
            }else{
                cnt++;
            }
        }
        cnt=0;
        for(int i=n-1;i>=0;i--){
            if(s.charAt(i)=='('){
                if(cnt<1) return false;
                cnt--;
            }else{
                cnt++;
            }
        }
        return true;
    }
}

NC199 字符串解码

描述
给一个加密过的字符串解码,返回解码后的字符串。
加密方法是:k[c] ,表示中括号中的 c 字符串重复 k 次,例如 3[a] 解码结果是 aaa ,保证输入字符串符合规则。不会出现类似 3a , 3[3] 这样的输入。
数据范围:输出的字符串长度满足1≤n≤50 

示例1
输入:"3[a]"
返回值:"aaa"

示例2
输入:"abc"
返回值:"abc"

示例3
输入:"3[3[b]]"
返回值:"bbbbbbbbb"
思路1:
	栈
思路2:
	递归法

NC208 每日温度

描述
根据往后 n 天的天气预报,计算每一天需要等待几天才会出现一次更高的气温,如果往后都没有更高的气温,则用 0 补位。
例如往后三天的气温是 [1,2,3] , 则输出 [1,1,0]
数据范围:1≤n≤10^5,每天的温度满足0≤temp≤100 
示例1
输入:[1,2,3]
返回值:[1,1,0]
示例2
输入:[2,4,5,9,10,0,9]
返回值:[1,1,1,1,0,1,0]
示例3
输入:[3,1,4]
返回值:[2,1,0]
思路:
	单调栈
import java.util.  ;
public class Solution {
    public int[] temperatures (int[] temperatures) {
        Stack<Integer> stack=new Stack<>();
        int n=temperatures.length;
        if(n==1) return new int[]{0};
        int[] res=new int[n];
        for(int i=n-1;i>=0;i--){
            if(stack.isEmpty()){
                res[i]=0;
                stack.push(i);
            }else{
                while(!stack.isEmpty() &&temperatures[i]>=temperatures[stack.peek()]){
                    stack.pop();
                }
                if(stack.isEmpty()){
                    res[i]=0;
                }else{
                    res[i]=stack.peek()-i;
                }
                stack.push(i);
            }
        }
        return res;
    }
}

NC 216 逆波兰表达式

描述
给定一个逆波兰表达式,求表达式的值。
数据范围:表达式长度满足1≤n≤10^4,表达式中仅包含数字和 + ,- ,    , / ,其中数字的大小满足∣val∣≤200 。
示例1  输入:["2","1","+","4","  "]  返回值:12
示例2  输入:["2","0","+"]  返回值:2
思路: 栈
	遇见数字直接压栈
	遇见符号直接计算
import java.util.  ;
public class Solution {
    public int evalRPN (String[] tokens) {
        Stack<String> stack=new Stack<>();
        for(int i=0;i<tokens.length;i++){
            if(isSign(tokens[i])){
                int n1=Integer.parseInt(stack.pop());
                int n2=Integer.parseInt(stack.pop());
                if(tokens[i].equals("+")){
                    stack.push(n1+n2+"");
                }else if(tokens[i].equals("-")){
                    stack.push(n2-n1+"");
                }else if(tokens[i].equals("  ")){
                    stack.push(n1  n2+"");
                }else if(tokens[i].equals("/")){
                    stack.push((int)(n2/n1)+"");
                }
            }else{
                stack.push(tokens[i]);
            }
        }
        return Integer.parseInt(stack.pop());
    }
    public boolean isSign(String str){
        return str.equals("+")||str.equals("-")||str.equals("  ")||str.equals("/");
    }
}

NC219 移掉 K 位数字

描述
给定一个以字符串表示的数字 num 和一个数字 k ,从 num 中移除 k 位数字,使得剩下的数字最小。如果可以删除全部数字则剩下 0
数据范围:num的长度满足1≤k≤n≤10^5,保证 num 中仅包含 0~9 的十进制数
示例1
输入:
"1432219",3
返回值:"1219"
说明:
移除 4 3 2 后剩下 1219 
示例2
输入:"10",1
返回值:"0"
思路:
首要目的是删除高位的大数(数组中排在索引小的位置),才能使得数字尽可能小。那么我们可以维持一个从栈底到栈顶单调不减的单调栈,在从高位向低位遍历num的各位数字时,不断检查栈中元素的单调性。
	一旦这个单调性被破坏,就表示高位数大,低位数小,这时候如果还剩下删除操作,就将栈顶元素弹出再把当前元素压栈(相当于移掉一个数);满足单调不减就直接把当前数字压栈。
	经过上面的过程遍历完数组后还有一点需要注意:就是需要去除结果数字的前导零。这样得到的才是一个合法的数字。
	
	1 单调栈弹出k个数字
	2 弹出所有并反转
	3 去掉头部的0
import java.util.  ;

public class Solution {
    public String removeKnums (String num, int k) {
        // write code here
        Stack<Character> stack=new Stack<>();
        for(int i=0;i<num.length();i++){
            while(k>0&&!stack.isEmpty()&&stack.peek()>num.charAt(i)){
                stack.pop();
                k--;
            }
            stack.push(num.charAt(i));
        }
        StringBuilder sb=new StringBuilder();
        while(!stack.isEmpty()) sb.append(stack.pop());
        sb=sb.reverse();
        String res= sb.toString();
        //把头部的0都抛出
        for(int i=0;i<res.length();i++){
            if(res.charAt(i)!='0'){
                return res.substring(i,res.length()).equals("")?"0":res.substring(i,res.length());
            }
        }
        return res;
    }
}

NC237 最大矩形

描述
给定一个仅包含 0 和 1 ,大小为 n  m 的二维二进制矩阵,找出仅包含 1 的最大矩形并返回面积。
数据范围:1≤n,m≤200  保证输入的矩形中仅含有 0 和 1
例如输入[[1,0,1,0,0],[1,1,1,1,0],[1,1,1,1,1],[1,0,0,1,0]]时,对应的输出为8,所形成的最大矩形如下图所示:

示例1
输入:[[1]]
返回值:1

示例2
输入:[[1,1],[0,1]]
返回值:2   

示例3
输入:[[0,0],[0,0]]
返回值:0

示例4
输入:[[1,0,1,0,0],[1,1,1,1,0],[1,1,1,1,1],[1,0,0,1,0]]
返回值:8
思路:
	和直方图最大面积类似,先求出来每个位置在纵向的连续的1的个数,包括自己
例子:
   [[1,0,1,0,0],
	[1,1,1,1,0],
	[1,1,1,1,1],
	[1,0,0,1,0]]
step 1 求纵向连续1的个数
	[1,0,1,0,0],
	[2,1,2,1,0],
	[3,2,3,2,1],
	[4,0,0,3,0]
step 2 单调栈 求每一行的最大矩形面积
import java.util.  ;
public class Solution {
    public int maximalRectangle (int[][] matrix) {
        int res=0;
        //遍历每一行
        for(int i=0;i<matrix.length;i++){
            //构造这一行的直方图
            int[] temp=new int[matrix[i].length];
            for(int j=0;j<matrix[i].length;j++){
                //某个位置为1
                if(matrix[i][j]==1){
                    //开始向上寻找连续的1的个数
                    int index=i,n=0;
                    while(index>=0&&matrix[index][j]==1){
                        n++;
                        index--;
                    }
                    temp[j]=n;
                }
            }
            res=Math.max(res,largestRectangleArea(temp));
        }
        return res;
    }
    //直方图最大面积
    public int largestRectangleArea(int[] heights) {
        int res=0;
        int[] newheights=new int[heights.length+2];
        for(int i=0;i<heights.length;i++){
            newheights[i+1]=heights[i];
        }
        Stack<Integer> stack=new Stack<>();
        for(int i=0;i<newheights.length;i++){
            while(!stack.isEmpty()&&newheights[stack.peek()]>newheights[i]){
                int cur=stack.pop();
                int l=stack.peek();
                int r=i;
                res=Math.max(res,(r-l-1)  newheights[cur]);
            }
            stack.push(i);
        }
        return res;
    }
}

NC240 计算器(一)

描述
给定一个字符串形式的表达式 s ,请你实现一个计算器并返回结果。
数据范围:表达式长度满足1≤∣s∣≤10^5,字符串中包含 + , -  , ( , ) ,保证表达式合法。
示例1 输入:"1+2"  返回值:3
示例2 输入:"1-1"   返回值:0
示例3 输入:"-0"  返回值:0
思路:和NC137一样
import java.util.  ;

public class Solution {
    public int calculate (String s) {
        s=s.replaceAll(" ","");//替换空格
        char[] chars=s.toCharArray();
        Stack<Integer> numops=new Stack<>();
        numops.add(0);//防止出现负数为第一个数字
        Stack<Character> signops=new Stack<>();
        for(int i=0;i<chars.length;i++){
            char c=chars[i];
            if(c=='('||c=='  '||c=='/'){
                signops.push(c);
            }else if(isNum(c)){
                String temp="";
                while(i<chars.length&&isNum(chars[i])){
                    temp+=chars[i];
                    i++;
                }
                i--;
                numops.push(Integer.parseInt(temp));
            }else if(c=='+'||c=='-'){
                while(!numops.isEmpty()&&!signops.isEmpty()
                      &&(signops.peek()=='+'||signops.peek()=='-'||signops.peek()=='  '||signops.peek()=='/')){
                    int n1=numops.pop();
                    int n2=numops.pop();
                    char sig=signops.pop();
                    numops.push(calculation(n2,n1,sig));
                }
                signops.push(c);
            }else if(c==')'){
                while(!numops.isEmpty()&&signops.peek()!='('){
                    int n1=numops.pop();
                    int n2=numops.pop();
                    char sig=signops.pop();
                    numops.push(calculation(n2,n1,sig));
                }
                signops.pop();
            }
        }
        while(!signops.isEmpty()){
            int n1=numops.pop();
            int n2=numops.pop();
            char sig=signops.pop();
            numops.push(calculation(n2,n1,sig));
        }

        return numops.peek();
    }

    public int calculation(int a,int b,char sign){
        switch(sign){
            case '+':return a+b;
            case '-':return a-b;
            case '  ':return a  b;
            case '/':return (int)(a/b);
            default :return 0;
        }
    }

    public boolean isNum(char c){
        if(c>='0'&&c<='9') return true;
        return false;
    }
}

NC241 计算器(二)

描述
给定一个字符串形式的表达式 s ,请你实现一个计算器并返回结果,除法向下取整。
数据范围:表达式长度满足1≤∣s∣≤10^5,字符串中包含 + , - ,    , / , 保证表达式合法。
示例1
输入:"1  10"
返回值:10

示例2
输入:"8  9-19"
返回值:53

示例3
输入:"100000  100  0"
返回值:0

示例4
输入:"100000  100/9"
返回值:1111111
思路:双栈
	1 符号 直接入栈
	2 数字 判断符号栈是否为空
		空 :直接入栈
		不为空:计算后入栈
import java.util.  ;

public class Solution {
    public int calculate (String s) {
        s=s.replaceAll(" ","");//替换空格
        char[] chars=s.toCharArray();
        Stack<Integer> numops=new Stack<>();
        numops.add(0);//防止出现负数为第一个数字
        Stack<Character> signops=new Stack<>();
        for(int i=0;i<chars.length;i++){
            char c=chars[i];
            if(isNum(c)){  
                //是数字
                String temp="";
                while(i<chars.length&&isNum(chars[i])){
                    temp+=chars[i];
                    i++;
                }
                i--;
                int n=Integer.parseInt(temp);
                //入栈
                if(!signops.isEmpty()){
                    char ss=signops.pop();
                    switch(ss){
                        case '+': numops.push(n);break;
                        case '-': numops.push(-n);break;
                        case '  ': numops.push(numops.pop()  n);break;
                        case '/': numops.push((int)(numops.pop()/n));break;
                        default:;
                    }
                }else{
                    numops.push(n);
                }
            }else{  //不是数字
                signops.push(c);
            }
        }
        while(numops.size()!=1){
            int n1=numops.pop();
            int n2=numops.pop();
            numops.push(n1+n2);
        }
        return numops.peek();
    }
    public boolean isNum(char c){
        if(c>='0'&&c<='9') return true;
        return false;
    }
}

版权声明:本文为qq_34329430原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。