实习校招面试手撕代码真题题型8——栈,单调栈

1 Linux路径处理

原题:71. 简化路径 - 力扣(LeetCode)

思路:
1.使用栈来存储路径

2.遍历路径,遇到 ‘…’ 则弹出栈顶元素,遇到 ‘.’ 或者空字符串则跳过,其他情况则入栈

3.最后将栈中元素用 ‘/’ 连接起来

public String simplifyPath(String path) {
    //将path用"\"切割
    String[] sp = path.split("/");

    Deque<String> stack = new ArrayDeque<>();
    for(String str : sp){
        if (str.equals("..")){ //当前字符串为".." 若栈不为空则栈顶出栈一个元素
            if(!stack.isEmpty())stack.pop();
        }else if(str.equals(".") || str.equals("")){ //若当前字符为"." 或是""空字符串(切割可能产生空字符串) 则跳过
            continue;
        }else{ //入栈
            stack.push(str);
        }
    }

    //用栈底开始出栈,拼接到sb中
    StringBuilder sb = new StringBuilder();

    while(!stack.isEmpty()){
        sb.append("/").append(stack.pollLast());
    }
    return sb.length() == 0 ? "/" : sb.toString();
}

2 小行星碰撞

735. 小行星碰撞 - 力扣(LeetCode)

 public int[] asteroidCollision(int[] asteroids) {
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        int n = asteroids.length;


        for(int i = 0; i < n; i ++){
            int cur = asteroids[i];
            boolean alive = true; //表示cur是否存在,默认为true

            //栈不为空,且cur与栈顶元素方向相反 发生碰撞
            while (alive && !stack.isEmpty() && (cur < 0 && stack.peek() > 0)){
                int absCur = Math.abs(cur);
                int absPeek = Math.abs(stack.peek());

                if (absCur < absPeek){//若cur的绝对值< peek,则碰撞后cur不存在, peek仍然存在
                    alive = false;
                }
                else if(absCur > absPeek){ //若cur的绝对值 > peek 则碰撞后cur存在,peek不存在
                    alive = true;
                    stack.pop();
                }else{ //若cur绝对值 == peek 则两者都不存在
                    alive = false;
                    stack.pop();
                }  
            }

            if (alive){
                stack.push(cur);
            }
        }

        int[] ans = new int[stack.size()];

        int j = 0;
        while (!stack.isEmpty()){
            ans[j] = stack.pollLast();
            j ++;
        }
        return ans;
    }

3 括号内字符串翻转

1190. 反转每对括号间的子串 - 力扣(LeetCode)

思路:

左括号,则将之前准备好的sb入栈,并重置sb

右括号 将当前sb翻转,并出栈一个字符串插到翻转后的sb最前面

    public String reverseParentheses(String s) {
        int n = s.length();

        StringBuilder sb = new StringBuilder();
        Deque<String> stack = new ArrayDeque<>();

        for (int i = 0; i < n; i ++){
            char c = s.charAt(i);

            if (c == '('){ //入栈'('之前的sb,然后重置sb
                stack.push(sb.toString());
                sb = new StringBuilder();
            }else if (c == ')'){//翻转')'之前的sb,并将栈顶元素出栈插到翻转后sb最前面
                sb.reverse();
                sb.insert(0, stack.pop());
            }else{ //普通字符 则加入sb
                 sb.append(c);
            }
        }
        return sb.toString();
    }

4 有效的括号

20. 有效的括号 - 力扣(LeetCode)

思路:遇到左括号则入栈,遇到右括号则出栈(出栈时需进行括号匹配)

 public boolean isValid(String s) {
       int n = s.length();

       Deque<Character> stack = new ArrayDeque<>();
       
       for (int i = 0; i < n; i++){
            char c = s.charAt(i);

            //当c为左括号 入栈
            if (c == '(' || c == '{' || c =='['){
                stack.push(c);
            }else{//当c为右括号,进行括号匹配
                
                //如果此刻栈为空,则没有左括号与该右括号匹配 返回false
                if (stack.isEmpty()) return false;

                //先将栈顶元素拿到(不是出栈)
                char peek = stack.peek();
                
                //括号匹配方法1,左右括号是同一类型时,匹配失败,返回false
                if (peek == '(' && c != ')') return false;
                if (peek == '[' && c != ']') return false;
                if (peek == '{' && c != '}') return false;
                //到这就是匹配成功 出栈
                stack.pop();
                
                //括号匹配方法2,左右括号是同一类型时,匹配成功,栈顶元素(左括号)出栈,若一直没匹配到最后返回false
//                if (peek == '(' && c == ')'){
//                    //匹配成功,栈顶元素出栈
//                    stack.pop();
//                }
//                if  (peek =='{' && c == '}'){
//                    stack.pop();
//                }
//                if (peek == '[' && c == ']'){
//                    stack.pop();
//                }
//                return false;
                
            }
       }
       //最后栈是空 才表明括号匹配全部成功,否则表示有括号匹配失败 返回false
        return stack.isEmpty() ? true : false;
    }

单调栈

1 移除k位数字,求最小数 (遇到换题)

402. 移掉 K 位数字 - 力扣(LeetCode)

思路:通过单调栈,保证每次新加入的字符都比前面的字符小,遇到大的字符则移除,这样可以形成最小的数。代码通过遍历和判断来移除尽量大的数字,并在必要时移除队列尾部的元素。

public String removeKdigits(String num, int k) {
        if (num.length() <= k) return "0";

        //使用双端队列来保存可能的最小数字
        LinkedList<Character> deque = new LinkedList<>();
        int n = num.length();

        //遍历num中的每个字符
        for (int i = 0; i < n; i++) {
            char c = num.charAt(i);
            //当队列不空且 k > 0 且队尾字符大于当前字符时,移除队尾字符
            while (!deque.isEmpty() && k >0 && deque.peekLast() > c){
                deque.pollLast(); //移除队尾元素
                k --; //移除的字符数减少一个
            }
            //将当前字符添加到队列的末尾
            deque.offerLast(c);
        }
        //如果还没够删够k位数字,继续删除队列尾部的字符
        for (int i = 0; i < k; i++) {
            deque.pollLast();
        }

        //构建最终结果
        StringBuilder sb = new StringBuilder();
        boolean leadingZero = true; //是否遇到前导零
        while (!deque.isEmpty()){
            char digit = deque.pollFirst(); //取出队列中的第一个字符
            //如果遇到前导零,则跳过
            if (leadingZero && digit == '0'){
                continue;
            }
            leadingZero = false; //一旦遇到非零字符,就不再是前导零
            sb.append(digit); //将非前导零字符添加到结果中
        }
        //如果结果为空,则返回0
        return sb.length() == 0 ? "0" : sb.toString();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值