算法训练营Day11

#Java #栈和队列

开源学习资料

Feeling and experiences:

有效的括号:力扣题目链接

对于这个处理字符,括号匹配的问题,在学习数据结构中也遇到过。

数据结构中的做法就是模拟栈,利用栈先进后出的特点。

以下是我第一次写所遇到的问题:

class Solution {
    public boolean isValid(String s) {
      //先创建一个栈,来进行辅助操作
      Stack stack = new Stack<>();
      //因为括号只有三种,可以直接都表示出来
      //用左括号做参考,把右括号入栈处理
       int count =0;  //后面又加了count来解决括号数目不一致问题 ,但这样不能解决右括号比左括号多的情况
       //如果长度为奇数,则一定不行
       if(s.length()%2 == 1){
           return false;
       }
      //遇到右括号,就把右括号入栈
      for(int i =0;i

此代码的注释看到很乱,因为我在第一遍写的时候,有很多问题和细节都没有考虑到。

我最开始只判断了左右括号是否匹配的问题,而没有考虑它们数目是否相等。

我的代码思路:以左括号为参考,把对应的右括号入栈,然后去判断这个右括号,如果它与当前的左括号匹配,则出栈。依次这样操作,如果栈为空,说明匹配成功,如果不为空则失败。

大体思路没问题,但里面还有很多细节没有处理。

比如还存在右括号多了的情况(因为是以左括号为参考)。

我就在基础上一步一步增删改查,加了长度判断(因为要匹配,长度为奇数肯定不行),又加了计数器,来判断左右括号数量是否一致(但是判断出现了问题)。

导致思路很混乱,越写越乱。

该代码最后还是没有解决右括号多了的问题。

算法训练营Day11_第1张图片

还是要整理好思路在下手~

其实写完思考一下,以我的方法来写的话,就只要解决了右括号比左括号多的问题就行。

因为我是以左括号为参照,加入栈的只有右括号,而右括号入栈的数量是基于左括号的,在if判断中,遇到了一个左括号就入栈一个右括号。那如果右括号的数量比左括号多,在该代码中是体现不出来的,所以还需要一个条件判断来控制。

因为外层for循环会遍历每一个字符,在if语句中只有遇到左括号才入栈与之对应的右括号,仔细想一下,如果没有遍历到左括号了,也就不会添加右括号,那么在循环里栈为空了,就代表右括号多了。

细品以下代码:

外层for循环会依次遍历执行,遍历到左括号就会入栈一个右括号,此时栈就不是空的了,匹配了再弹出来,这个时候栈空了,但是这一次循环的语句也执行完了,又到下一次循环了。

class Solution {
    public boolean isValid(String s) {
        Stack stack = new Stack<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            //碰到左括号,就把相应的右括号入栈
            if (ch == '(') {
                stack.push(')');
            }else if (ch == '{') {
                stack.push('}');
            }else if (ch == '[') {
                stack.push(']');
            } else if (stack.isEmpty() || stack.peek() != ch) {
                return false;
            }else {//如果是右括号判断是否和栈顶元素匹配
                stack.pop();
            }
        }
        //最后判断栈中元素是否匹配
        return stack.isEmpty();
    }
}

因为是栈和队列的练习,就先不写map集合的解答了。

删除字符串中的所有相邻重复项:力扣题目链接

算法训练营Day11_第2张图片

删除相邻且相同的元素很简单,但是如上述示例:删除了还要合并后再判断。(类似消消乐)

一次一次操作,那这样效率就太低了。

class Solution {
    public String removeDuplicates(String s) {
    //利用栈,先依次把字符串中的元素入栈,遇到遍历的元素与栈顶元素相同,则出栈栈顶元素
    Deque deque = new LinkedList<>();
    StringBuffer res = new StringBuffer();
    for(int i=0;i

本次我是用到了双端队列,这样就既可以用模拟栈来消除元素后,再模拟队列存放结果。

实现了栈和队列的结合使用。

注意判断栈空的情况,不然会容易抛出异常。

特别是在:if(deque.isEmpty() || ch != deque.peek()),为什么会去判断是否为空?

1. 如果栈为空,直接将当前字符入栈,因为栈中没有元素,无需比较。
2. 如果栈不为空,检查当前字符是否与栈顶元素不同,如果不同,则入栈;如果相同,则说明有相邻重复字符,出栈栈顶元素。

通过这个条件,代码能够正确处理栈为空的情况,避免了潜在的空栈异常。

逆波兰表达式求值:力扣题目链接

 该题目,最开始还没有读懂是什么意思。

算法训练营Day11_第3张图片

后面看了代码随想录的文字讲解,又把该问题转变为了栈的运用。

在力扣的官方解答中,也有动态示意图

把题意理解到了就非常好做了

class Solution {
    public int evalRPN(String[] tokens) {
    Deque deque = new LinkedList<>();
    for(int i =0;i

练习完以上的题目,有很多的收获。

题目的难度是依次递增的,但花费的时间也是递增的。虽然第一个题是最简单的,但是存在的细节也很多。昨天归纳完了栈和队列的模拟与总结了方法,今天就是实战。

从做题的流程下来,在第一个题上反而花费了最多的时间,很多条件的判断是最开始是没想到的,到慢慢琢磨,细品。把第一个题的问题处理完后,再来做后面的题就越来越快了。

今日的三道题主要是用到了栈的原理,还要多加巩固API的使用和对栈结构的处理!

回廊一寸相思地

落月成孤倚~

Fighting!

你可能感兴趣的:(算法)