代码随想录算法训练营D10|栈与队列part01:232.用栈实现队列,20. 有效的括号,1047. 删除字符串中的所有相邻重复项

目录

栈与队列

232. 用栈实现队列

225. 用队列实现栈

20. 有效的括号

1047. 删除字符串中的所有相邻重复项


栈与队列

        这里说的栈与队列可以理解为容器适配器,各自有其接口,比如有push、pop,符合先进后出的规则,其底层结构主要为数组和链表。而队列符合先进先出的规则,其底层结构默认是以deque

 

232. 用栈实现队列

public class MyQueue {
    /**
     * 负责进栈
     */
    Stack<Integer> stackIn;
    /**
     * 负责出栈
     */
    Stack<Integer> stackOut;


    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();

    }

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

    public int pop() {
        // 只有当out为空时才从in导数据
        if (stackOut.isEmpty()) {
            while (!stackIn.isEmpty()) {
                stackOut.push(stackIn.pop());
            }
        }
        return stackOut.pop();
    }

    public int peek() {
        int popData = this.pop();
        stackOut.push(popData);
        return popData;
    }

    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }
}

225. 用队列实现栈

        一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。

public class MyStack {

    Queue<Integer> queue;

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

    public void push(int x) {
        queue.add(x);
    }

    public int pop() {
        rePosition();
        return queue.poll();
    }

    public int top() {
        rePosition();
        int result = queue.poll();
        queue.add(result);
        return result;
    }

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

    private void rePosition() {
        int size = queue.size();
        size--;
        while (size-- > 0) {
            queue.add(queue.poll());
        }
    }
}

20. 有效的括号

括号匹配是使用栈解决的经典问题

分析不匹配情况:

因为题目要求:左右匹配、顺序匹配、类型要匹配,因而我们可以在遍历时将对应的右边括号放到栈内,遍历左边结束后,就可从栈中取出来进行比对。

public class ValidParentheses {

    public boolean isValid(String s) {
        // 因为要求成对匹配,所以长度为奇数时,返回错误
        if (s.length() % 2 != 0) {
            return false;
        }

        LinkedList<Character> deque = new LinkedList<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            if (ch == '(') {
                deque.push(')');
            } else if (ch == '{') {
                deque.push('}');
            } else if (ch == '[') {
                deque.push(']');
            } else if (deque.isEmpty() || deque.peek() != ch) {
                // 如果栈为空 或者 当前遍历值不等于栈顶值,则无效
                return false;
            } else {
                // 右括号匹配,则弹出栈顶,继续遍历
                deque.pop();
            }
        }
        // 如果为空,说明字符串满足条件
        return deque.isEmpty();
    }
}

 

1047. 删除字符串中的所有相邻重复项

属于匹配问题,依然用栈来解决

public class RemoveAdjacentDuplicates {


    /**
     * 使用 Deque 作为堆栈
     * @param s
     * @return
     */
    public String removeDuplicatesByStack(String s) {
        // ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
        ArrayDeque<Character> deque = new ArrayDeque<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            if (deque.isEmpty() || ch != deque.peek()) {
                deque.push(ch);
            }else {
                deque.pop();
            }
        }
        // 剩余的元素拼接即可
        String str = "";
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }

    /**
     * 字符串直接作为栈,省去了栈还要转为字符串的操作。
     * @param s
     * @return
     */
    public String removeDuplicatesByString(String s) {
        // 可以用StringBuffer代替栈,用StringBuilder更快
//        StringBuilder res = new StringBuilder();
        StringBuffer res = new StringBuffer();

        // 栈顶指针
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (top >= 0 && res.charAt(top) == ch) {
                res.deleteCharAt(top);
                top--;
            }else {
                res.append(ch);
                top++;
            }
        }
        return res.toString();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值