算法刷题笔记11/60 | 第五章 栈与队列P2 | 20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

20 有效的括号

无脑暴力破解

思路:用HashMap存储对应左右括号信息,创造两个栈。一个栈插入左括号,一个栈根据key值插入右括号。当插入右括号时,如与第二个栈相同,第一个左括号则匹配成功,出栈。

public boolean isValid(String s) {
    // 1. 存储匹配信息
    HashMap<Character, Character> hm = new HashMap<>();
	hm.put('(', ')');
	hm.put('[', ']');
	hm.put('{', '}');

	// 2.用两个栈实现匹配
	Stack<Character> s1 = new Stack<>();
	Stack<Character> s2 = new Stack<>();


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

    // x 和 s2元素相同时 完成匹配s1 s2出栈
    if (!s2.isEmpty() && x == s2.peek()) {
        s1.pop();
        s2.pop();
    }

    // 没有匹配,如果是key里的值则入栈,s2存对应匹配字符
    else {
        if (!hm.containsKey(x)) return false;
        s1.push(x);
        s2.push(hm.get(x));
    }
}

	// 全部匹配成功则true
	return s1.isEmpty();

}

思考优化

反思自己写的步骤,s1 基本没有有效参与。s1的出栈完全可以用s2出栈代替 而s2可以用if else代替HashMap存储对应左右括号,减少空间复杂度

public boolean isValid(String s) {


    // s1 用处有限,基本没有有效参与
    // s2可以用if else代替HashMap,减少空间复杂度
    Stack<Character> s2 = new Stack<>();

for (int i = 0; i < s.length(); i++) {
    char x = s.charAt(i);
    // 如果是左括号追加右括号为下一个匹配
    if (x == '(')
        s2.push(')');
    else if (x == '[') {
        s2.push(']');
    } else if (x == '{') {
        s2.push('}');
    }
        // 如果不是左括号,判空且判断栈顶元素是否为要匹配元素
    else if (s2.isEmpty() || s2.peek() != x) {
        return false;
    }
        // 如果是匹配元素则出栈
    else s2.pop();
}

// 全部匹配成功则true
return s2.isEmpty();
}

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

思路:遍历元素入栈,相同则出栈,不相同则入栈

public String removeDuplicates(String s) {
    Stack<Character> s1 = new Stack<>();

for (int i = 0; i < s.length(); i++) {
    char x = s.charAt(i);
    // 匹配到相同元素 - 出栈
    if(!s1.isEmpty() && s1.peek() == x) s1.pop();
        // 不是相同元素 - 进栈
    else s1.push(x);
}

//剩余的元素即为不重复的元素
String str = "";
while (!s1.isEmpty()) {
    str = s1.pop() + str;
}
return str;

}

150 逆波兰表达式求值

思路:由于数组支持逆波兰表达式,因此先前不需要做任何判断,直接进入遍历:数字进栈,运算符则出栈运算。 ❗ 注意:减法和加法需要注意数字排列

public int evalRPN(String[] tokens) {
    Stack<Integer> s = new Stack<>();

    for (String str : tokens) {
        // 需要注意减法和除法时的顺序
        switch (str) {
            case "+" -> {
                Integer num1 = s.pop();
                Integer num2 = s.pop();
                s.push(num1 + num2);
            }
            case "-" -> {
                Integer num1 = s.pop();
                Integer num2 = s.pop();
                // 注意
                s.push(num2 - num1);
            }
            case "*" -> {
                Integer num1 = s.pop();
                Integer num2 = s.pop();
                s.push(num1 * num2);
            }
            case "/" -> {
                Integer num1 = s.pop();
                Integer num2 = s.pop();
                // 注意
                s.push(num2 / num1);
            }
            default -> s.push(Integer.valueOf(str));
        }
    }
    return s.pop();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值