【LeetCode题解】栈系类

思路

栈,最小栈,单调栈

例题

735. 行星碰撞

leetCode-725

给定一个整数数组 asteroids,表示在同一行的行星。

对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。每一颗行星以相同的速度移动。

找出碰撞后剩下的所有行星。碰撞规则:两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞。

示例 1:

输入:asteroids = [5,10,-5]
输出:[5,10]
解释:10 和 -5 碰撞后只剩下 10 。 5 和 10 永远不会发生碰撞。
示例 2:

输入:asteroids = [8,-8]
输出:[]
解释:8 和 -8 碰撞后,两者都发生爆炸。
示例 3:

输入:asteroids = [10,2,-5]
输出:[10]
解释:2 和 -5 发生碰撞后剩下 -5 。10 和 -5 发生碰撞后剩下 10 。
示例 4:

输入:asteroids = [-2,-1,1,2]
输出:[-2,-1,1,2]
解释:-2 和 -1 向左移动,而 1 和 2 向右移动。 由于移动方向相同的行星不会发生碰撞,所以最终没有行星发生碰撞。

提示:

2 <= asteroids.length <= 104
-1000 <= asteroids[i] <= 1000
asteroids[i] != 0

解题思路

思路一

本题可使用这个数据结构进行辅助判断。将数组中的行星元素依次放入栈中,每次压入栈的时候,与栈顶元素进行进行判断,是否能碰撞消除。最终栈中留下来的元素就是碰撞后剩下的行星。

  • 思路
  • 边界
  • 细节
  • 优化
  • 代码实现
    public int[] asteroidCollision(int[] asteroids) {
        if (asteroids == null || asteroids.length == 0) {
            return new int[] {};
        }
        LinkedList<Integer> stack = new LinkedList<>();
        for (int i = 0; i < asteroids.length; i++) {
            boolean flag = true;
            while (!stack.isEmpty() && stack.peek() > 0 && asteroids[i] < 0) {
                if (Math.abs(asteroids[i]) > stack.peek()) {
                    stack.pop();
                } else if (Math.abs(asteroids[i]) == stack.peek()) {
                    stack.pop();
                    flag = false;
                    break;
                } else {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                stack.push(asteroids[i]);
            }
        }
        int[] result = new int[stack.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = stack.removeLast();
        }
        return result;
    }

最小栈

155. 最小栈

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

push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。

思路一
使用一个辅助栈,从上到下保存栈的最小值。

细节
辅助栈的入栈判断条件是细节,注意是等号,而且如果辅助栈为空的时候,也是可以入栈的

代码

public class LeetCode155 {

    Deque<Integer> stack1 = new ArrayDeque<>();

    Deque<Integer> stack2 = new ArrayDeque<>();

    public LeetCode155() {
        stack1 = new ArrayDeque<>();
        stack2 = new ArrayDeque<>();
    }

    public void push(int val) {
        stack1.push(val);
        if (stack2.isEmpty() || stack2.peek() >= val) { // 判断条件是细节,注意是等号,而且如果辅助栈为空的时候,也是可以入栈的
            stack2.push(val);
        }
    }

    public void pop() {
        if (!stack1.isEmpty()) {
            int pop = stack1.pop();
            if (!stack2.isEmpty() && stack2.peek() == pop) {
                stack2.pop();
            }
        }
    }

    public int top() {
        if (!stack1.isEmpty()) {
            return stack1.peek();
        }
        throw new RuntimeException("栈中元素为空,此操作非法");

    }

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

思路二
不适用辅助栈。
将前一个最小值保存起来,保存到栈中。

代码

    class MinStack {

        Deque<Integer> stack1;

        int min;

        public MinStack() {
            stack1 = new ArrayDeque<>();
            min = Integer.MAX_VALUE;
        }

        public void push(int val) {
            if (val <= min) {
                int preMin = min;
                stack1.push(preMin);// 保存之前的min值
                min = val;
            }
            stack1.push(val);
        }

        public void pop() {
            if (!stack1.isEmpty()) {
                int pop = stack1.pop();
                if (pop == min) {
                    int preMin = stack1.pop();// 弹出前一个最小值
                    min = preMin;
                }
            }
        }

        public int top() {
            if (!stack1.isEmpty()) {
                return stack1.peek();
            }
            throw new RuntimeException("stack is empty");
        }

        public int getMin() {
            return min;
        }
    }

思路三
用数组实现栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值