【代码随想录】第五章-栈与队列

【代码随想录】第五章-栈与队列


第五章 栈与队列

1 有效括号

20.有效括号

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

有效字符串需满足:左括号必须用相同类型的右括号闭合;左括号必须以正确的顺序闭合;每个右括号都有一个对应的相同类型的左括号。

输入:s = "(\[\])" 输出:true

思路:

如果是左括号,就放进去,如果是右括号,就弹出来一个看匹不匹配,匹配就继续下一个

java 复制代码
class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '{' || c == '[') {
                stack.push(c);
            } else {
                if (stack.isEmpty()) {
                    return false;
                }
                char top = stack.pop();
                if ((c == ')' && top != '(') ||
                    (c == '}' && top != '{') ||
                    (c == ']' && top != '[')) {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

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

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

给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 s 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

输入:"abbaca" 输出:"ca"

思路:

用栈匹配

java 复制代码
class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> S = new ArrayDeque<Character>();
        char[] cs = s.toCharArray();
        int i = 0;
        int len = s.length();
        S.push(cs[i++]);
        while (i < len) {
            if (S.isEmpty()) {
                S.push(cs[i++]);
                continue;
            }
            char top = S.peek();
            if (top != cs[i]) {
                S.push(cs[i++]);
            } else {
                S.pop();
                i++;
            }
        }
        StringBuffer sb=new StringBuffer();
        while(!S.isEmpty()){
            sb.append(S.pop());
        }
        return sb.reverse().toString();
    }
}

3 逆波兰表达式求值

150.逆波兰表达式求值

根据逆波兰表示法,求表达式的值。有效的运算符包括+,-,*,/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。说明:整数除法只保留整数部分。给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为0的情况。

输入:s = "abbaca" 输出:"ca"

思路:

java 复制代码
class Solution {
    public int evalRPN(String[] tokens) {
        Deque<String> S = new ArrayDeque<String>();
        int len=tokens.length;
        int i=0;
        S.push(tokens[i++]);
        while(i<len){
            if(tokens[i].matches("-?\\d+")){
                S.push(tokens[i++]);
            }
            else{
                int b=Integer.parseInt(S.pop());
                int a=Integer.parseInt(S.pop());
                if(tokens[i].equals("+")){
                    S.push(String.valueOf(a+b));
                }
                else if(tokens[i].equals("-")){
                    S.push(String.valueOf(a-b));
                }
                else if(tokens[i].equals("/")){
                    S.push(String.valueOf(a/b));
                }
                else if(tokens[i].equals("*")){
                    S.push(String.valueOf(a*b));
                }
                i++;
            }
        }
        return Integer.parseInt(S.peek());
    }
}

4 滑动窗口最大值

239.滑动窗口最大值

给你一个整数数组nums,有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。

输入:nums = 1,3,-1,-3,5,3,6,7, k = 3 输出:3,3,5,5,6,7

思路:

用一个单调队列来存储对应的下标,每当窗口滑动的时候,直接取队列的头部指针对应的值放入结果集即可。

队列头结点需要在i - k + 1, i范围内,不符合则要弹出。

既然是单调,就要保证每次放进去的数字要比末尾的都大,否则队尾也弹出

因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了

java 复制代码
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int len=nums.length;
        int []res=new int[len-k+1];
        Deque<Integer> Q=new ArrayDeque<>();
        int ri=0;
        int ni=0;
        for(int i=0;i<len;i++){
            while(!Q.isEmpty()&&Q.peek()<i-k+1){
                Q.poll();
            }
            while(!Q.isEmpty()&&nums[Q.peekLast()]<nums[i]){
                Q.pollLast();
            }
            Q.add(i);
            if(i>=k-1){
                res[ni++]=nums[Q.peek()];
            }
        }
        return res;        
    }
}

5 第K个高频元素

347.前K个高频元素

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。。

输入:nums = 1,1,1,2,2,3, k = 2 输出:1,2

思路:

Hashmap排序

java 复制代码
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        int []res=new int[k];
        Deque<Integer> Q=new ArrayDeque<>();
        Map<Integer,Integer>map=new HashMap<>();
        int len=nums.length;
        for(int i=0;i<len;i++){
             map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
        List<Map.Entry<Integer, Integer>> entryList =
 											new ArrayList<>(map.entrySet());
        entryList.sort((entry1, entry2) ->
entry2.getValue().compareTo(entry1.getValue()));
        for (int i = 0; i < k; i++) {
            res[i]=entryList.get(i).getKey();
        }
        return res;
    }
}
Tip:Integer数组排序
java 复制代码
int[] arr = {5, 3, 8, 1, 2};
Integer[] arr2 = {5, 3, 8, 1, 2};
for(int i=0;i<arr.length;i++){
    arr2[i] = arr[i];
}
  • 如果不用比较器的话,只有对象数组arr2可以用自定义排序,arr只能先升序后手动翻转
  • 对于对象数组可以用lamada表达式
java 复制代码
Arrays.sort(arr, (a, b) -> b - a)
Arrays.sort(arr2, (a,b)->b.compareTo(a));
Tip:Hashmap排序/Arraylist排序

先转为List:List<Map.Entry<...,...>>list= new ArrayList<>(map.entrySet());

用谁排序用谁,用value排value,用key排key。List.sort((e1,e2)->e1.getValue().compareTo(e2.getValue()));


相关推荐
小江的记录本4 分钟前
【JVM虚拟机】类加载机制:类加载器、双亲委派模型、好处、破坏双亲委派的场景(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·后端·python·spring·面试
李少兄5 分钟前
Spring 对象创建范式:依赖注入与直接实例化的边界抉择
java·后端·spring
小马爱打代码12 分钟前
Spring源码中的设计模式实战:从理论到源码的深度解析
java·spring·设计模式
埃菲尔铁塔_CV算法12 分钟前
基于扩张卷积与双分支参数调控的低光照图像增强算法完整研究与工程解析
人工智能·神经网络·算法·机器学习·计算机视觉
老码观察14 分钟前
数环通iPaaS架构设计的结构化与模块化方法论——从高内聚低耦合到工程落地的完整指南
java·服务器·网络
迈巴赫车主16 分钟前
优先队列(PriorityQueue)
数据结构·算法
hai31524754319 分钟前
有规则的AI编制操作系统演进过程展示
人工智能·程序人生·算法·逻辑回归·创业创新
数据仓库搬砖人22 分钟前
SHAP 详解:从博弈论原理到 XGBoost 实战
算法
老鱼说AI23 分钟前
统计学习方法第七章:支持向量机精讲(超硬核长文深入预警!)
人工智能·深度学习·神经网络·算法·机器学习·支持向量机·学习方法
Devin~Y24 分钟前
智慧物流+AIGC客服Java大厂面试:Spring Boot、Kafka、Redis、JVM与RAG Agent实战
java·jvm·spring boot·redis·spring cloud·kafka·rag