時念
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
    • JavaScript 基础
  • 后端笔记

    • Java
    • Spring
    • 算法
    • 高可用
    • 高并发
  • 工作问题

    • 问题记录
  • 各类工具使用
  • GitHub技巧
  • 博客搭建
  • 面试题库

    • 零碎
    • 面试常见题目汇总
  • 面试心得

    • 面试集锦
    • 杂言碎语
  • 摘抄收录

    • ☆ 励志鸡汤
    • ❀ 人间烟火
    • ☣ 万物沦丧
    • ✌ 关掉烦恼
    • ✲ 小酒馆
  • 读书笔记

    • 《小狗钱钱》
    • 《穷爸爸富爸爸》
    • 《聪明人使用方格笔记本》
  • 学习
  • 心情杂货
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub

時念

一个有梦想的后端小菜鸡(✪ω✪)
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
    • JavaScript 基础
  • 后端笔记

    • Java
    • Spring
    • 算法
    • 高可用
    • 高并发
  • 工作问题

    • 问题记录
  • 各类工具使用
  • GitHub技巧
  • 博客搭建
  • 面试题库

    • 零碎
    • 面试常见题目汇总
  • 面试心得

    • 面试集锦
    • 杂言碎语
  • 摘抄收录

    • ☆ 励志鸡汤
    • ❀ 人间烟火
    • ☣ 万物沦丧
    • ✌ 关掉烦恼
    • ✲ 小酒馆
  • 读书笔记

    • 《小狗钱钱》
    • 《穷爸爸富爸爸》
    • 《聪明人使用方格笔记本》
  • 学习
  • 心情杂货
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub
  • java

  • spring

  • 问题记录

  • 算法

    • 链表
    • 双指针
    • 二叉树
    • 回溯
    • (伪)二分
    • 堆
    • 贪心
    • 动态规划
    • 多维动态规划
    • 技巧
    • 数组
    • 子串
    • 滑动窗口
    • 哈希
    • (伪)栈
      • 有效括号
      • 最小栈
      • 字符串解码
      • 每日温度
      • 柱状图中最大的矩形
    • 数组混淆点整理
  • 高可用

  • 后端
  • 算法
時念
2023-12-14

(伪)栈

最近提交时间 题目 题目难度 提交次数
7 分钟前 #84 柱状图中最大的矩形 困难 4 次
20 分钟前 #739 每日温度 中等 4 次
30 分钟前 #394 字符串解码 中等 1 次
2 小时前 #155 最小栈 中等 1 次
2 小时前 #20 有效的括号 简单 11 次

为什么叫(伪)栈?

是因为有些题目,直接蛮力法做,或者利用奇淫巧技更为简单。

面试在栈不熟的情况下(尤其是单调栈这种<温度,雨水等>),直接两层for搞定 ,虽然超时,但面试不扣分

备注:

1、有效括号 包含时放入栈中的是value if条件下直接返回false 包含value时 的判断 !stack.pop().equals(c)

2、最小栈 除去pop外 都是 peek操作

3、字符串解码 (过)

4、每日温度 ,倒着循环,内部 对 j while循环 记录值 每一步完成都要break;

5、柱状图 最大矩形 就按照这个做

int res = 0;

​ for(int i = 0; i< heights.length; i++){

​ int l = Integer.MAX_VALUE;

​ for(int j = i; j< heights.length; j++){

​ l = Math.min(l, heights[j]);

​ res = Math.max(res, l*(j-i+1));

​ }

​ }

​ return res;

# 有效括号

class Solution {
    public boolean isValid(String s) {
        Map<Character, Character> map = new HashMap<>();
        map.put('(', ')');
        map.put('[', ']');
        map.put('{', '}');
        Stack<Character> stack = new Stack();
        for(int i = 0; i< s.length(); i++){
            char c = s.charAt(i);
            if(map.containsKey(c)){
                stack.push(map.get(c));
            }
            if(map.containsValue(c)){
                if(stack.isEmpty()){
                    return false;
                }
                if(!stack.pop().equals(c)){
                    return false;
                }
            }

        }
        return stack.isEmpty();
    }
}
思路:
  1、利用了栈 + 奇淫巧技
  2、先定义一个限定的map
  3、然后循环字符串,如果map的key包含 char 就放入 栈
  4、否则 判断是否包含value ,之后 如果栈是空的直接返回false(这就是 括号不对称的场景
  5、然后将栈pop 判断是否与当前char 相等,不相等就是false
  6、最后如果栈是空的 那就是完美 括弧, 只要栈里面有没弹出来的 就是不完美的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 最小栈

class MinStack {

    Stack<Integer> stack;
    Stack<Integer> help;

    public MinStack() {
        stack  =new Stack<>();
        help = new Stack<>();
    }
    
    public void push(int val) {
        stack.push(val);
        if(help.isEmpty() || help.peek() >= val){
            help.push(val);
        } else{
            help.push(help.peek());
        }

    }
    
    public void pop() {
        if(!stack.isEmpty()){
            stack.pop();
            help.pop();
        }

    }
    
    public int top() {
          if(!stack.isEmpty()){
            return stack.peek();
        }
        throw new RuntimeException("栈中元素为空,此操作非法");
    }
    
    public int getMin() {
        if(!help.isEmpty()){
            return help.peek();
        }
         throw new RuntimeException("栈中元素为空,此操作非法");
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */
思路:
  1、定义一个辅助栈
  2、getmin 就是 help 出栈
  3、top 就是 stack 出栈
  4、pop 只要 stack不是空的  就一起pop
  5、push stack直接 push 然后help 首先是空的 并且help 当前val 比 peek后的元素 小 才会放入help 否则 help元素就自己放入自己。 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# 字符串解码

class Solution {
    public String decodeString(String s) {
      while (s.contains("[")) {
                  Pattern pattern = Pattern.compile("(\\d+)\\[([a-z]+)\\]");
                  Matcher matcher = pattern.matcher(s);

                  if (matcher.find()) {
                      int n = Integer.parseInt(matcher.group(1));
                      String str = matcher.group(2);

                      // 用字符串补齐方法将 n 个 s 拼接 替换掉编码
                      String replacement = new String(new char[n]).replace("\0", str);
                      s = s.replaceFirst("(\\d+)\\[([a-z]+)\\]", replacement);
                  } else {
                      break;
                  }
              }
      return s;
    }
}
思路:
  1、奇淫巧技了 ,正则不好搞 ,但写出来很装杯
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 每日温度

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        // int[] answer =  new int[temperatures.length];
        // for(int i = 0; i< temperatures.length; i++){
        //     int now = temperatures[i];
        //     for(int j = i+1; j< temperatures.length; j++){
        //         int next = temperatures[j];
        //         if(next > now){
        //             answer[i] = j-i;
        //             break;
        //         }
        //     }
        // }
        // return answer;
        int[] res = new int[temperatures.length];
        //从后面开始查找
        for (int i = res.length - 1; i >= 0; i--) {
            int j = i + 1;
            while (j < res.length) {
                if (temperatures[j] > temperatures[i]) {
                    //如果找到就停止while循环
                    res[i] = j - i;
                    break;
                } else if (res[j] == 0) {
                    //如果没找到,并且res[j]==0。说明第j个元素后面没有
                    //比第j个元素大的值,因为这一步是第i个元素大于第j个元素的值,
                    //那么很明显这后面就更没有大于第i个元素的值。直接终止while循环。
                    break;
                } else {
                    //如果没找到,并且res[j]!=0说明第j个元素后面有比第j个元素大的值,
                    //然后我们让j往后挪res[j]个单位,找到那个值,再和第i个元素比较
                    j += res[j];
                }
            }
        }
        return res;
    }

}
思路:
  1、第一种方法 暴力破解,简单 但是时间复杂度不符合
  2、第二种 在暴力破解的基础上 优化 利用找不到就停止循环和跳跃多个元素的方式 进行判断比较 致使时间复杂度来到 n*log(n)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 柱状图中最大的矩形

class Solution {
    // public int largestRectangleArea(int[] heights) {
    //     // int  ans = 0;
    //     // for(int left =0; left< heights.length; left++){
    //     //     int height = Integer.MAX_VALUE;
    //     //     for(int right = left; right < heights.length; right++){
    //     //         height = Math.min(height , heights[right]);
    //     //         ans = Math.max(ans, (right-left+1) * height);
    //     //     }
    //     // }
    //     // return ans;

    // }
    public int largestRectangleArea(int[] heights) {
        // 这里为了代码简便,在柱体数组的头和尾加了两个高度为 0 的柱体。
        int[] tmp = new int[heights.length + 2];
        System.arraycopy(heights, 0, tmp, 1, heights.length); 
        
        Deque<Integer> stack = new ArrayDeque<>();
        int area = 0;
        for (int i = 0; i < tmp.length; i++) {
            // 对栈中柱体来说,栈中的下一个柱体就是其「左边第一个小于自身的柱体」;
            // 若当前柱体 i 的高度小于栈顶柱体的高度,说明 i 是栈顶柱体的「右边第一个小于栈顶柱体的柱体」。
            // 因此以栈顶柱体为高的矩形的左右宽度边界就确定了,可以计算面积🌶️ ~
            while (!stack.isEmpty() && tmp[i] < tmp[stack.peek()]) {
                int h = tmp[stack.pop()];
                area = Math.max(area, (i - stack.peek() - 1) * h);   
            }
            stack.push(i);
        }

        return area;
    }
}
思路:
  1、暴力破解,但要注意height的判断,其余就是双循环赋值面积而已,  但是缺点就是时间超时
  2、第二个单调栈 理解起来还是要麻烦一点的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
编辑
上次更新: 2024/03/26, 9:03:00
哈希
数组混淆点整理

← 哈希 数组混淆点整理 →

最近更新
01
database-shard-dynamic-expand
03-26
02
README
03-26
03
database-shard-global-id-generate
03-26
更多文章>
Theme by Vdoing | Copyright © 2019-2024 時念 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式