d10栈的应用

第五章 栈与队列part02

今日内容: 

  1.  20. 有效的括号
  1.  1047. 删除字符串中的所有相邻重复项
  1.  150. 逆波兰表达式求值

20. 有效的括号 

题目:给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

分析有哪几种不匹配的情况

第一种情况,字符串里左方向的括号多余了 ,所以不匹配。

第二种情况,括号没有多余,但是 括号的类型没有匹配上。

第三种情况,字符串里右方向的括号多余了,所以不匹配。

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

字符串遍历完之后,栈是空的,就说明全都匹配了。

class Solution {

    public boolean isValid(String s) {

        Deque<Character> deq = new LinkedList<>();

        int length = s.length();

        for(int i=0;i<length;i++)

        {

            char ch = s.charAt(i);

            if(ch=='(') deq.push(')');

            else if(ch=='[') deq.push(']');

            else if(ch=='{') deq.push('}');

            else if(deq.isEmpty()||deq.pop()!=ch) return false;

        }

        return deq.isEmpty();

    }

}

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

题目:给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。然后再去做对应的消除操作。

从栈中弹出剩余元素因为从栈里弹出的元素是倒序的,所以再对字符串进行反转一下,就得到了最终的结果。

ArrayDeque会比LinkedList在除了删除元素这一点外会快一点

ArrayDeque 作为 堆栈(FILO 使用时的方法:

堆栈方法

等效的双端队列方法

push(e)

addFirst(e)

pop(e)

removeFirst(e)

peek()

peekFirst()

使用 Deque 作为堆栈

class Solution {

    public String removeDuplicates(String s) {

        ArrayDeque<Character> deq = new ArrayDeque<>();

        for(int i=0;i<s.length();i++)

        {

            char ch = s.charAt(i);

            if(deq.isEmpty()||ch!=deq.peek()) deq.push(ch);

            else deq.pop();

        }

        String result ="";

        while(!deq.isEmpty()) result=deq.pop()+result;

        return result;

    }

}

拿字符串直接作为栈

class Solution {

    public String removeDuplicates(String s) {

       StringBuffer result = new StringBuffer();

       int top = -1;

       for(int i=0;i<s.length();i++)

       {

           char ch = s.charAt(i);

           if(top>=0&&ch==result.charAt(top))

           {

               result.deleteCharAt(top);

               top--;

           }

           else{

               result.append(ch);

               top++;

           }

       }

       return result.toString();

    }

}

delete()方法和deleteCharAt()方法都是用来删除StringBuffer字符串指定字符索引的方法。

delete(int a,int b)方法:包含两个参数,使用时删除索引从ab(包括a不包括b)的所有字符;

deleteCharAt(int s)方法:只有一个参数,使用时删除索引为a的字符。

③双指针;

class Solution {

    public String removeDuplicates(String s) {

       char[] chars =s.toCharArray();

       int slow = 0;

       for(int fast=0;fast<chars.length;fast++)

       {

        chars[slow] = chars[fast];

        if(slow>0&&chars[slow]==chars[slow-1]) slow--;

        else slow++;

       }

       return new String(chars,0,slow);

    }

}

4.String s = new String(char数组,起始下标,长度);左闭右开。

150. 逆波兰表达式求值

题目:给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

逆波兰表达式相当于是二叉树中的后序遍历

将中缀表达式,转化为后缀表达式之后计算机可以利用栈来顺序处理,不需要考虑优先级了。也不用回退了, 所以后缀表达式对计算机来说是非常友好的。

在进一步看,本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么这岂不就是一个相邻字符串消除的过程,和1047.删除字符串中的所有相邻重复项中的对对碰游戏是不是就非常像了。

这和1047. 删除字符串中的所有相邻重复项是差不多的,只不过本题不要相邻元素做消除了,而是做运算!

class Solution {

    public int evalRPN(String[] tokens) {

        Deque<Integer> stack = new LinkedList<>();

        for(String s:tokens)

        {

            if("+".equals(s)) stack.push(stack.pop()+stack.pop());

            else if("-".equals(s))stack.push(-stack.pop()+stack.pop());

            else if("*".equals(s))stack.push(stack.pop()*stack.pop());

            else if("/".equals(s)){

                int temp1 = stack.pop();

                int temp2 = stack.pop();

                stack.push(temp2/temp1);

            }

            else{

                stack.push(Integer.valueOf(s));

            }

        }

        return Integer.valueOf(stack.pop());

    }

}

  • 36
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值