硅基计划4.0 算法 栈

1755615270672



1. 删除字符串的相邻的重复项

题目链接
这道题可以利用我们的模拟哈希表
如果当前元素已经出现过了我们就直接跳过,否则我们就加入
我们可以使用一个字符串去模拟这个过程,当我遍历原先字符串的时候,我们可以去检查当前要添加的字符之前是否已经出现
如果出现了,我们就把当前拼接的字符删除,否则我们就正常拼接

class Solution {
    public String removeDuplicates(String s) {
        StringBuilder str = new StringBuilder();
        char [] ss = s.toCharArray();
        for(char ch : ss){
            if(str.length() > 0 && ch == str.charAt(str.length()-1)){
                str.deleteCharAt(str.length()-1);
            }else{
                str.append(ch);
            }
        }
        return str.toString();
    }
}

2. 比较含退格键的字符

题目链接
这一题还是可以利用刚刚到思想,我们定义两个字符串去模拟栈的过程
遇到退格符就把栈顶元素删除,如果本身字符串就是空的,使用退格符是无效的

class Solution {
    public boolean backspaceCompare(String s, String t) {
        char [] ss = s.toCharArray();
        char [] tt = t.toCharArray();
        StringBuilder str1 = new StringBuilder();
        StringBuilder str2 = new StringBuilder();
        for(char ch : ss){
            if(str1.length() > 0 && ch == '#'){
                str1.deleteCharAt(str1.length()-1);
            }else{
                //如果字符串本身就是空的,没必要再让#进来
                if(ch == '#'){
                    continue;
                }
                str1.append(ch);
            }
        }
        for(char ch : tt){
            if(str2.length() > 0 && ch == '#'){
                str2.deleteCharAt(str2.length()-1);
            }else{
                //如果字符串本身就是空的,没必要再让#进来
                if(ch == '#'){
                    continue;
                }
                str2.append(ch);
            }
        }
        return str1.toString().equals(str2.toString());
    }
}

3. 验证出栈顺序

题目链接
这个之前讲过了,这里不再重复赘述

class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        Stack<Integer> stack = new Stack<>();
        int pos = 0;
        for(int x:pushed){
            //先放元素后判断,这样可以直接让栈顶元素和poped中的元素进行比较
            stack.push(x);
            while(!stack.isEmpty() && stack.peek() == popped[pos]){
                stack.pop();
                pos++;
            }
        }
        return stack.isEmpty();
    }
}

4. 基本计算器II

题目链接
这个题就很有意思了,这题本质上要使用两个栈去模拟,一个栈存数字,一个栈存运算符
但是这一题我们可以使用一个栈存数字,一个字符类型遍历表示当前的运算符去实现

我们指针去遍历字符串的时候,如果当前碰到了一个数,如果一个多位数。不要忘记要把多位数提取出来
如果遍历到当前数,操作符是+,我们就正常放入元素,如果是-,我们则要放入相反数
如果遇到/或者是*,则要进行计算,把结果放入
我们把最开始操作符初始化成+

接下来我们来去模拟这个过程
image-20250930201445475

class Solution {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<>();
        char [] ss = s.toCharArray();
        char op = '+';
        int pos = 0;
        while(pos < ss.length){
            while(pos < ss.length && ss[pos] == ' '){
                pos++;
            }
            int temp = 0;
            while(pos < ss.length && !isOp(ss[pos]) && ss[pos] != ' '){
                //可能会遇到这种情况:2 _ _ ,如果我们不加ss[pos] != ' ',_ 表示' '
                //编译器会误以为_ _ 也是数字,导致计算错误
                temp = temp*10+(ss[pos]-'0');
                pos++;
            }
            if(op == '+'){
                stack.push(temp);
            }else if(op == '-'){
                stack.push(-temp);
            }else if(op == '*'){
                stack.push(stack.pop()*temp);
            }else if(op == '/'){
                stack.push(stack.pop()/temp);
            }
            if(pos >= ss.length){
                break;
            }
            op = ss[pos];
            pos++;
        }
        int ret = 0;
        while(!stack.isEmpty()){
            ret += stack.pop();
        }
        return ret;
    }

    private boolean isOp(char ch){
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }
}

5. 字符串解码

题目链接
这题的核心就是如果存在多组[],我们就需要找到最里面的一层[],然后逐层解码
我们如果遇到第一个],我们就可以开始解码了
我们可以定义两个栈,一个栈用来存数字,表示需要重复的字符次数
一个栈用来存每一层解码后的字符串
我们以一个具体的实例来说

image-20250930204017844

image-20250930204030087

class Solution {
    public String decodeString(String s) {
        Stack<Integer> stackNum = new Stack<>();
        Stack<String> stackStr = new Stack<>();
        stackStr.push("");
        char [] ss = s.toCharArray();
        int pos = 0;
        while(pos < ss.length){
            if(isDigit(ss[pos])){
                int temp = 0;
                while(pos < ss.length && isDigit(ss[pos])){
                    temp = temp*10+(ss[pos]-'0');
                    pos++;
                }
                stackNum.push(temp);
            }else if(ss[pos] == '['){
                pos++;
                StringBuilder str = new StringBuilder();
                while(pos < ss.length && ss[pos] >= 'a' && ss[pos] <= 'z'){
                    str.append(ss[pos]);
                    pos++;
                }
                stackStr.push(str.toString());
            }else if(ss[pos] == ']'){
                int num = stackNum.pop();
                String puzzle = stackStr.pop();
                StringBuilder tmp = new StringBuilder();
                while(num > 0){
                    tmp.append(puzzle);
                    num--;
                }
                StringBuilder popS = new StringBuilder(stackStr.pop());
                popS.append(tmp);
                stackStr.push(popS.toString());
                pos++;
            }else{
                StringBuilder str = new StringBuilder();
                while(pos < ss.length && ss[pos] >='a' && ss[pos] <='z'){
                    str.append(ss[pos]);
                    pos++;
                }
                StringBuilder popS = new StringBuilder(stackStr.pop());
                popS.append(str);
                stackStr.push(popS.toString());
            }
        }
        return stackStr.pop();
    }

    private boolean isDigit(char ch){
        int num = ch-'0';
        return num >= 0 && num < 10;//>=0 应对100[leetcode]这个例子
    }
}

当然,我的代码复杂了,你也可以简化代码,我这这个只是便于展示图中思想


希望本篇文章对您有帮助,有错误您可以指出,我们友好交流

END
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值