【己】栈,堆,队列

部分借鉴

0.表达式的计算

224. 基本计算器
方法1:将中缀表达式转换成后缀表达式,然后使用上面的方法
方法2:直接使用两个栈进行求解,一个放数字一个放表达式

方法3. 使用一个栈求解
很巧妙,使用一个栈,对于操作符,左右括号和数字采取不同的出入栈策略。

class Solution {
    public int calculate(String s) {
    //遇到右括号开始计算,知道左括号停止
        //遇到符号只是改变正负号,遇到数字进行计算。
        //使用一个保存结果temp
        Stack<Integer> stack = new Stack<>();
        int sign = 1;
        int res = 0;
        int operand = 0; //存放暂时的操作数
        for (int i = 0; i < s.length(); i++) {
            char t = s.charAt(i);
            if(Character.isDigit(t)){
                operand = operand * 10 + (int)(t - '0');
            }
            //遇到操作符就进行计算
            else if (t == '+'){
                res += operand * sign;
                sign = 1;
                operand = 0;
            }else if (t == '-'){
                res += operand * sign;
                sign = -1;
                operand = 0;
            }else if(t == '('){
                //左括号,把前面的符号记录下来。
                stack.push(sign);
                stack.push(res);                
                //此时的res是括号里的res,左边的结果被存在了栈中               
                //遇到左括号,进入括号里从新开始
                sign = 1;
                res = 0;
                //operand肯定是0
            }else if (t == ')'){
                //遇到右括号,进行计算
                res += operand * sign;
                res = stack.pop() + res * stack.pop();
                operand = 0;
            }
            
        }
        return res + sign * operand;
    }
}

227. 基本计算器 II

策略:
二、处理加减法
现在进一步,如果输入的这个算式只包含加减法,而且不存在空格,你怎么计算结果?我们拿字符串算式1-12+3为例,来说一个很简单的思路:
1、先给第一个数字加一个默认符号+,变成+1-12+3。
2、把一个运算符和数字组合成一对儿,也就是三对儿+1,-12,+3,把它们转化成数字,然后放到一个栈中。
3、将栈中所有的数字求和,就是原算式的结果。
三,处理乘除法 从栈里弹出一个数(即符号前面的前面的结果)与符号前面的cur进行计算后入栈。

class Solution {
    public int calculate(String s) {
        //记录前一个数的值,+-进栈,乘除计算、
        Stack<Integer> stack = new Stack<>();
        int sign = '+';
        int res = 0;
        int cur = 0;
        for (int i = 0; i < s.length(); i++) {
            char t = s.charAt(i);
            if(Character.isDigit(t)){
                cur = cur * 10 + (int)(t - '0');
            }
            if(t =='+'||t =='-'||t =='*'||t =='/' || i == s.length()-1){
                if(sign == '+'){
                    stack.push(cur);
                }
                else if(sign == '-'){
                    stack.push(-cur);
                }
                else if(sign == '*'){
                    stack.push(stack.pop() * cur);
                }
                else if(sign == '/'){
                    stack.push(stack.pop() / cur);
                }
                cur = 0;
                sign = t;
            }
        }
        for (Integer i : stack){
            res += i;
        }
        return res;
    }
}

150. 逆波兰表达式求值
逆波兰式,也叫后缀表达式,一个好处就是只需要运算符,不需要括号,不会产生歧义。
注意:

  • 不需要对栈进行判断,最后栈中的值一定是所求值
  • 每个case后记得加break
    public int evalRPN(String[] tokens) {
        //遇到符号弹出来计算,然后在放进去,直到栈不为空或者
        Stack<Integer> stack  = new Stack<>();
        int res = 0;
        for (int i = 0; i < tokens.length; i++) {
            int s1;
            int s2;
            switch (tokens[i]){
                case "+" :
                    s1 = stack.pop();
                    s2 = stack.pop();
                    stack.push(s1+s2);
                    break;
                case "-" :
                    s1 = stack.pop();
                    s2 = stack.pop();
                    stack.push(s1-s2);
                    break;
                case "*" :
                    s1 = stack.pop();
                    s2 = stack.pop();
                    stack.push(s1*s2);
                    break;
                case "/" :
                    s1 = stack.pop();
                    s2 = stack.pop();
                    stack.push(s1/s2);
                    break;
                default:
                    stack.push(Integer.valueOf(tokens[i]));
                    break;
            }
        }
        return stack.pop();
    }
}

1. 用栈实现队列

232. Implement Queue using Stacks (Easy)

Leetcode / 力扣

栈的顺序为后进先出,而队列的顺序为先进先出。使用两个栈实现队列,一个元素需要经过两个栈才能出队列,在经过第一个栈时元素顺序被反转,经过第二个栈时再次被反转,此时就是先进先出顺序。

class MyQueue {

    private Stack<Integer> in = new Stack<>();
    private Stack<Integer> out = new Stack<>();

    public void push(int x) {
        in.push(x);
    }

    public int pop() {
        in2out();
        return out.pop();
    }

    public int peek() {
        in2out();
        return out.peek();
    }

    private void in2out() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) {
                out.push(in.pop());
            }
        }
    }

    public boolean empty() {
        return in.isEmpty() && out.isEmpty();
    }
}

2. 用队列实现栈

225. Implement Stack using Queues (Easy)

Leetcode / 力扣

在将一个元素 x 插入队列时,为了维护原来的后进先出顺序,需要让 x 插入队列首部。而队列的默认插入顺序是队列尾部,因此在将 x 插入队列尾部之后,需要让除了 x 之外的所有元素出队列,再入队列。

class MyStack {

    private Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<>();
    }

    public void push(int x) {
        queue.add(x);
        int cnt = queue.size();
        while (cnt-- > 1) {
            queue.add(queue.poll());
        }
    }

    public int pop() {
        return queue.remove();
    }

    public int top() {
        return queue.peek();
    }

    public boolean empty() {
        return queue.isEmpty();
    }
}

3. 最小值栈

155. Min Stack (Easy)

Leetcode / 力扣

class MinStack {

    private Stack<Integer> dataStack;
    private Stack<Integer> minStack;
    private int min;

    public MinStack() {
        dataStack = new Stack<>();
        minStack = new Stack<>();
        min = Integer.MAX_VALUE;
    }

    public void push(int x) {
        dataStack.add(x);
        min = Math.min(min, x);
        minStack.add(min);
    }

    public void pop() {
        dataStack.pop();
        minStack.pop();
        min = minStack.isEmpty() ? Integer.MAX_VALUE : minStack.peek();
    }

    public int top() {
        return dataStack.peek();
    }

    public int getMin() {
        return minStack.peek();
    }
}

对于实现最小值队列问题,可以先将队列使用栈来实现,然后就将问题转换为最小值栈,这个问题出现在 编程之美:3.7。

4. 用栈实现括号匹配

20. Valid Parentheses (Easy)

Leetcode / 力扣

"()[]{}"

Output : true
public boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();
    for (char c : s.toCharArray()) {
        if (c == '(' || c == '{' || c == '[') {
            stack.push(c);
        } else {
            if (stack.isEmpty()) {
                return false;
            }
            char cStack = stack.pop();
            boolean b1 = c == ')' && cStack != '(';
            boolean b2 = c == ']' && cStack != '[';
            boolean b3 = c == '}' && cStack != '{';
            if (b1 || b2 || b3) {
                return false;
            }
        }
    }
    return stack.isEmpty();
}

最长有效括号

32. 最长有效括号

class Solution {
    public int longestValidParentheses(String s) {
        Stack<Integer> stack = new Stack<>();
        int start = 0;
        int max = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '('){
                stack.push(i);
            }else{
                if (stack.isEmpty()){
                    start  = i + 1;
                }else{
                    stack.pop();
                    if (stack.isEmpty()){
                        max = Math.max(max, i - start + 1);
                    }else{ //()()()
                        max = Math.max(max, i - stack.peek());//此时不加1,(((()这种情况,匹配栈顶前一个
                    }
                }
            }
        }
        return max;
    }
}

5. 数组中元素与下一个比它大的元素之间的距离

739. Daily Temperatures (Medium)

Leetcode / 力扣

Input: [73, 74, 75, 71, 69, 72, 76, 73]
Output: [1, 1, 4, 2, 1, 1, 0, 0]

在遍历数组时用栈把数组中的数存起来,如果当前遍历的数比栈顶元素来的大,说明栈顶元素的下一个比它大的数就是当前元素。

public int[] dailyTemperatures(int[] temperatures) {
    int n = temperatures.length;
    int[] dist = new int[n];
    Stack<Integer> indexs = new Stack<>();
    for (int curIndex = 0; curIndex < n; curIndex++) {
        while (!indexs.isEmpty() && temperatures[curIndex] > temperatures[indexs.peek()]) {
            int preIndex = indexs.pop();
            dist[preIndex] = curIndex - preIndex;
        }
        indexs.add(curIndex);
    }
    return dist;
}
class Solution {
    public int[] dailyTemperatures(int[] T) {
        int[] res=new int[T.length];
        Stack<Integer> s = new Stack<>();
        for(int i=0;i<T.length;i++){
            while(s.size() > 0 && T[i] > T[s.peek()]){
                int a = s.pop();
                res[a] = i - a;
            }
            s.push(i);
        }
        return res;
    }
}

6. 循环数组中比当前元素大的下一个元素

503. Next Greater Element II (Medium)

Leetcode / 力扣

Input: [1,2,1]
Output: [2,-1,2]
Explanation: The first 1's next greater number is 2;
The number 2 can't find next greater number;
The second 1's next greater number needs to search circularly, which is also 2.

与 739. Daily Temperatures (Medium) 不同的是,数组是循环数组,并且最后要求的不是距离而是下一个元素。

public int[] nextGreaterElements(int[] nums) {
    int n = nums.length;
    int[] next = new int[n];
    Arrays.fill(next, -1);
    Stack<Integer> pre = new Stack<>();
    for (int i = 0; i < n * 2; i++) {
        int num = nums[i % n];
        while (!pre.isEmpty() && nums[pre.peek()] < num) {
            next[pre.pop()] = num;
        }
        if (i < n){
            pre.push(i);
        }
    }
    return next;
}

每日温度

739. 每日温度

  • 栈里面放索引
  • 外层循环的个数是数组的大小,内存循环判断是否是空栈.
class Solution {
    public int[] dailyTemperatures(int[] T) {
        int[] res=new int[T.length];
        Stack<Integer> s = new Stack<>();
        for(int i=0;i<T.length;i++){
            while(s.size() > 0 && T[i] > T[s.peek()]){
                int a = s.pop();
                res[a] = i - a;
            }
            s.push(i);
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值