例题集 栈

  1. 用数组实现大小固定的栈
  2. 实现一个特殊的栈,在实现栈基本功能的基础上,在实现返回栈中最小元素的操作
  3. 用栈结构实现队列结构
  4. 删除字符串中所有相邻相同字符
  5. 删除最外层括号

1.用数组实现大小固定的栈
思想:

  1. 用index指向的位置为下一个数所要存放的地方
  2. 若要存放数,先判断是否还能放数,再将index++,把数存进去
  3. 若要取数,先判断是否还能取数,再将index–(可以不用把数取出,因为下一个要存进的数会覆盖掉)

在这里插入图片描述

    public static class ArrayStack{
        private Integer[] arr;
        private Integer size;

        public ArrayStack(int initSize){
            if (initSize < 0){
                throw new IllegalArgumentException("error");
            }
            arr = new Integer[initSize];
            size = 0;
        }

        //只读不取
        public Integer peek(){
            if (size ==0){
                return null;
            }
            return arr[size-1];
        }

        //放
        public void push(int obj){
            if (size == arr.length){
                throw new ArrayIndexOutOfBoundsException("full");
            }
            arr[size++] = obj;
        }

2.实现一个特殊的栈,在实现栈基本功能的基础上,在实现返回栈中最小元素的操作

要求:pop、push、getMin时间复杂度为O(1),设计的栈类型可以使用现成的栈结构

时间复杂度为O(1),则getMin时不能遍历数组

思路:

  1. 准备两个栈,Data栈存放正常数据,Min栈存放最小值
  2. 往Data栈中存进数时,比较当前数与Min栈栈顶数大小
    若存进数>Min栈栈顶数 ->往Min栈重复压入栈顶数
    若存进数<Min栈栈顶数 ->往Min栈压入存进数
    在这里插入图片描述
public static void main(String[] args) {
        StackOpration stackOpration = new StackOpration();
        stackOpration.stackData.clear();

        stackOpration.push(1);
        stackOpration.push(3);
        stackOpration.push(1);
        stackOpration.push(3);

        Integer min = stackOpration.getMin();
        System.out.println(min);
    }
    
public static class StackOpration{
        private Stack<Integer> stackData;
        private Stack<Integer> stackMin;

        public StackOpration(){
            this.stackData = new Stack<>();
            this.stackMin = new Stack<>();
        }

        //存数
        public void push(int num){
            //第一次存
            if (stackData.isEmpty()){
                stackData.add(num);
                stackMin.add(num);
            }else if (!stackData.isEmpty() && num > stackMin.peek()){
                //存进来的数 > Min栈栈顶
                stackData.add(num);
                stackMin.add(stackMin.peek());
            }else{
                //存进来的数 < Min栈栈顶
                stackData.add(num);
                stackMin.add(num);
            }
        }

        //取数
        public void pop(){
            if (!stackData.isEmpty()){
                stackData.pop();
                stackMin.pop();
            }else {
                throw new RuntimeException("empty");
            }
        }

        //取出最小值
        public Integer getMin(){
            if (!stackMin.isEmpty()){
                return stackMin.peek();
            }else{
                throw new RuntimeException("empty");
            }
        }
    }

3.用栈结构实现队列结构

  1. 创建两个栈,stackPush只存放数,stackPop只取出数
  2. 只往stackPush中存放数
  3. 取出数时,先将stackPush所有数倒进stackPop,弹出stackPop栈顶;再将stackPop所有数倒进stackPush
//仅用栈实现队列结构
public class StackToQueue12 {
    public static void main(String[] args) {

        TwoStackToQueue twoStackToQueue = new TwoStackToQueue();

        twoStackToQueue.push(1);
        twoStackToQueue.push(2);
        twoStackToQueue.push(3);
        twoStackToQueue.push(4);
        twoStackToQueue.push(5);

        Integer pop1 = twoStackToQueue.pop();
        System.out.println(pop1);

        Integer pop2 = twoStackToQueue.pop();
        System.out.println(pop2);

        Integer peek3 = twoStackToQueue.peek();
        System.out.println(peek3);

    }

    public static class TwoStackToQueue{
        private Stack<Integer> stackPush;
        private Stack<Integer> stackPop;

        public TwoStackToQueue(){
            this.stackPop = new Stack<>();
            this.stackPush = new Stack<>();
        }

        //存数
        public void push(int num){
            stackPush.push(num);
        }

        //取数
        public Integer pop(){
            //全局变量 记录返回值
            Integer num;

            //判空
            if (stackPush.isEmpty()){
                throw new RuntimeException("empty");
            }

            //将stackPush所有数倒进stackPop
            while (!stackPush.isEmpty()){
                stackPop.push(stackPush.pop());
            }

            num = stackPop.pop();

            //再将stackPop所有数倒进stackPush
            while (!stackPop.isEmpty()){
                stackPush.push(stackPop.pop());
            }

            return num;
        }

        //只读不取
        public Integer peek(){
            //全局变量 记录返回值
            Integer num;

            //判空
            if (stackPush.isEmpty()){
                throw new RuntimeException("empty");
            }

            //将stackPush所有数倒进stackPop
            while (!stackPush.isEmpty()){
                stackPop.push(stackPush.pop());
            }

            num = stackPop.peek();

            //再将stackPop所有数倒进stackPush
            while (!stackPop.isEmpty()){
                stackPush.push(stackPop.pop());
            }

            return num;
        }
    }
}

4.删除字符串中所有相邻相同字符
题目:
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

思路1
stack
1.用一个stack装入字符
如果与栈顶相同	->	直接删除
如果与栈顶不同	->	加入
2.用一个Sting字符串同步
//时间 5.16%
//空间 5.03%
    public static String removeDuplicates(String s) {
        if (s == null){
            return null;
        }

        Stack<Character> stack = new Stack<>();
        String res = "";

        for (int i = 0;i < s.length();i++){
            char c = s.charAt(i);

            if (!stack.isEmpty() && stack.peek() == c){
                stack.pop();
                res = res.substring(0,res.length() - 1);
                continue;
            }else {
                stack.push(c);
                res += c;
            }
        }


        return res;
    }
思路2
用StringBuffer代替stack
StringBuffer内部实现了类似stack的入栈出栈操作
//时间 81.61%
//空间 69.98%
    public static String removeDuplicates(String s) {
        if (s == null){
            return null;
        }

        StringBuffer buffer = new StringBuffer();
        int top = -1;
        for (int i = 0;i < s.length();i++){
            char c = s.charAt(i);
            if (top >= 0 && buffer.charAt(top) == c){
                buffer.deleteCharAt(top);
                top--;
            }else {
                buffer.append(c);
                top++;
            }
        }

        return buffer.toString();
    }

5.删除最外层括号
实例1
输入:s = “(()())(())”
输出:"()()()"

实例2
输入:s = “(()())(())(()(()))”
输出:"()()()()(())"

//时间 100%
//空间 24.54%
    public static String removeOuterParentheses(String s) {
        if(s == null){
            return null;
        }

        int number = 0;
        StringBuffer stack = new StringBuffer();

        for (char c:
             s.toCharArray()) {

            //如果number > 1 说明这个(非栈底
            if (c == '(' && ++number > 1){
                stack.append(c);
            }
            if (c == ')' && --number > 0){
                stack.append(c);
            }
        }

        return stack.toString();
    }
//时间 100%
//空间 43.74%
    public static String removeOuterParentheses(String s) {

            StringBuilder sb = new StringBuilder();
            int level = 0;
            for (char c : s.toCharArray()) {
                if (c == ')') --level;
                if (level >= 1) sb.append(c);
                if (c == '(') ++level;
            }
            return sb.toString();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值