算法通关村第四关——栈白银挑战笔记

本篇内容主要强化使用栈解决其他问题的能力,主要涉及了括号匹配这一热门问题,此外补充了辅助栈实现最大栈最小栈这一类问题的解决思路。

1.括号匹配问题

类似括号匹配问题,表达式求值问题等,都可以通过栈来实现。

如何判断括号是否匹配,例如[)不能匹配、[]可以匹配?答:我们可以用Map来实现,将匹配的符号当作K-V存入Map中,左括号作为K,右括号作为V。(这样做可以避免大量的逻辑判断!)

如何使用栈完成括号匹配任务?答:遍历每个字符,左括号压栈,右括号则判断栈顶元素对应的正确右括号当前遍历的右括号是否相等,相等则当前字符匹配成功,左括号出栈!如果遍历完毕,且栈空,则括号匹配任务完成!直接上代码!

    public static boolean isValid(String s) {
        HashMap map = new HashMap<>();
        map.put('(',')');
        map.put('[',']');
        map.put('{','}');
        Stack stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char item = s.charAt(i);
            if(map.containsKey(item)){//左括号
                stack.push(item);
            }else{//右括号
                if(!stack.isEmpty()){
                    char left = stack.pop();
                    char rightChar = map.get(left);
                    if(rightChar != item){
                        return false;
                    }
                }else{
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }

2.最小栈

题目见LeetCode155,描述为设计一个支持push,pop,top操作,并能在常数时间内检索到最小元素的栈。

我的分析:对于一个栈,如果想记录最小元素的话,可以使用一个变量min来记录,但是问题出在!如果某次操作使得最小元素弹栈了,那么min该如何变化?本能的希望可以记录第二小的元素,那么依次需要记录第三小、第四小....的元素。难道要开个数组?并且每次弹栈的元素并非最小元素呀!头好痛,似乎没思路了....

别怕!paper tiger罢了!我来给你补充一个辅助栈的知识点!辅助栈就用用于辅助记录当前栈内最小元素的!

算法通关村第四关——栈白银挑战笔记_第1张图片

 左侧是元素栈,右侧是辅助栈:用于存储元素栈内每个元素作为栈顶时栈内的最小值。

元素入栈,辅助栈需要比较入栈元素元素栈内最小元素(即辅助栈栈顶元素)的大小,将较小的值压入辅助栈中。

元素出栈,需要将辅助栈和元素栈同时弹栈。

厘清逻辑直接上代码!

class MinStack {
    Deque stack;
    Deque minStack;
    public MinStack() {
        stack = new LinkedList<>();
        minStack = new LinkedList<>();
        minStack.push(Integer.MAX_VALUE);
    }

    public void push(int x) {
        stack.push(x);
        minStack.push(Math.min(x, minStack.peek()));
    }

    public void pop() {
        stack.pop();
        minStack.pop();
    }

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

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

 3.最大栈

最大栈最小栈问题异曲同工!单独拎出来总结复盘的原因在于,它比最小栈多了一个功能要求:弹出栈内最大元素!题目见LeetCode716。

前面的逻辑已经全部实现了!那如何实现弹出栈内最大元素这一逻辑呢?比如一个栈:【栈底2 4 6 7 3 2栈顶】,需要弹栈7,使栈变成【栈底2 4 6 3 2栈顶】。

根据栈LIFO(后进先出)我们知道,如果7出栈,那么2,3必须依次出栈!可是最大元素7弹栈后,元素3、2仍然还在栈内,这是什么情况?答:元素2,3先弹栈后压栈!

那么弹出栈内最大元素的逻辑呼之欲出!依次弹出元素栈内元素,当弹出元素是最大元素,将原来弹出栈的非最大元素重新压入栈中!厘清逻辑,直接上代码!

class MaxStack {
    Stack stack;
    Stack maxStack;

    public MaxStack() {
        stack = new Stack<>();
        maxStack = new Stack<>();
        maxStack.push(Integer.MIN_VALUE);
    }

    public void push(int x) {
        stack.push(x);
        maxStack.push(Math.max(maxStack.peek(), x));
    }

    public int pop() {
        maxStack.pop();
        return stack.pop();
    }

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

    public int peekMax() {
        return maxStack.peek();
    }

    public int popMax() {
        int max = maxStack.peek();
        Stack tmpStack = new Stack<>();
        while(max!=stack.peek()){
            tmpStack.push(stack.pop());
            maxStack.pop();
        }
        stack.pop();
        maxStack.pop();
        while(!tmpStack.isEmpty()){
            push(tmpStack.pop());
        }
        return max;
    }
}

OK,《算法通关村第三关——数组白银挑战笔记》结束,喜欢的朋友三联加关注!关注鱼市带给你不一样的算法小感悟!(幻听)

再次,感谢鱼骨头教官的学习路线!鱼皮的宣传!小y的陪伴!ok,拜拜,第四关第三幕见!

你可能感兴趣的:(笔记)