【每日刷题】栈与队列-LC394、LC347、LC215

题外话:感觉脑子没长到栈这块…最近刷栈的题都好难啊…哭哭…坚持坚持!多刷几遍就好了!!

1. LC394.字符串解码

题目链接

先说数据结构。
维护两个栈:一个栈存之前的字符串,另一个栈存之后的字符串的重复次数(数字)
维护两个变量:res表示目前遍历到的字符组成的字符串,k表示遍历到的数字组成的数字

工作原理:
最开始的字符串为""。
遇到字符时:存到res里。
遇到数字时:存到k里。
遇到左括号:把左括号前面的字符串,以及左括号内要循环的次数(数字),分别入栈,即res和k入栈。然后res和k重置。
遇到右括号:说明此时的res为最小单位,将数字栈里的栈顶元素出栈,这个数字将是res循环的次数。然后将字符串栈里的栈顶元素出栈,这个元素是括号前的字符串,后面需要拼接res。拼接后,形成新的res。不入栈。等遇到左括号再入栈。

例:
3[a2[c]] 看成 ""3[a2[c]]

图片版:
在这里插入图片描述

文字版:
在这里插入图片描述
代码
注意当字符是数字字符的处理逻辑。

  1. c >= '0' && c <= '9' 来确定当前字符是不是数字字符
  2. c-'0' 得到当前字符代表的数字,将字符转为数字
  3. k = k * 10 + (c-'0'); 这个也很妙。如果k已经有数字了,例如k已经等于12了,这时又遍历到3,那么就是k*10再加上当前的数字,123。
class Solution {
    public String decodeString(String s) {
        int k = 0;
        StringBuilder res = new StringBuilder();
        Stack<StringBuilder> stack_Res = new Stack<>();
        Stack<Integer> stack_K = new Stack<>();

        for (char c : s.toCharArray()){
            if (c >= '0' && c <= '9'){
                k = k * 10 + (c-'0');
            }
            else if (c == '['){
                stack_Res.push(res);
                stack_K.push(k);
                res = new StringBuilder();
                k = 0;
            }
            else if (c == ']'){
                int count = stack_K.pop();
                StringBuilder temp = new StringBuilder();
                for (int i=0; i<count; i++){
                    temp.append(res);
                }
                res = stack_Res.pop().append(temp);
            }
            else{
                res.append(c);
            }
        }

        return res.toString();
    }
}

2. LC347、前K个高频元素

题目链接
解法一:

  1. 遍历一遍,建立哈希表存储数字与出现频次的映射。
  2. 维护一个元素数目为k的小顶堆。(堆中存放的是元素,但是priority queue可以按照自定义顺序排序,自定义顺序为:元素的频次)。
  3. 当有新元素来的时候,与堆顶元素作比较,若频次比堆顶元素大,则该元素应放到前k个高频元素中,所以堆顶元素出队列,该元素加队列。堆会自动按定义顺序排序。
  4. 最终堆中的元素就是前K个高频元素。

时间复杂度:
建立哈希表:n;小顶堆本身维护:logk;遍历哈希,维护小顶堆:nlogk;遍历堆存进数组:k
所以整体时间复杂度为O(nlogk)

空间复杂度:
哈希表:n,小顶堆:k。
所以整体空间复杂度为O(n)

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //建立哈希表维护 数值与频次 的键值对
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : nums){
            if (map.containsKey(i)){
                map.put(i, map.get(i)+1);
            }else{
                map.put(i, 1);
            }
        }
        
        //定义PriorityQueue存放前k个高频元素
        PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){
            @Override
            public int compare(Integer a, Integer b){
                return (map.get(a) - map.get(b));
            }
        });

        //遍历map,更新堆
        for (Integer key: map.keySet()){
            if (queue.size() < k){
                queue.offer(key);
            }else{
                if (map.get(key) > map.get(queue.peek())){
                    queue.poll();
                    queue.offer(key);
                }
            }
        }

        //输出堆元素
        int[] array = new int[k];
        for (int i=0; i<k; i++){
            array[i] = queue.poll();
        }
        return array;

    }
}

解法二:

  1. 遍历一遍,建立哈希表存储数字与出现频次的映射。
  2. 将Map.entrySet<>存放进list,list排序,按照自定义规则排序(按照频次,即value值从大到小排序)
  3. 获取list中前k个元素的key值

时间复杂度:
建立哈希表:n;放进list:n;sort方法排序:nlogn;遍历堆存进数组:k
所以整体时间复杂度为O(nlogn)

空间复杂度:
O(n)

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //建立哈希表维护 数值与频次 的键值对
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : nums){
            if (map.containsKey(i)){
                map.put(i, map.get(i)+1);
            }else{
                map.put(i, 1);
            }
        }

		//将entryset放进list,对list进行排序
		List<Map.Entry<Integer, Integer>> list = new ArrayList<>();
		for (Map.Entry<Integer, Integer> entry: map.entrySet()){
			list.add(entry);
		}
		Collections.sort(list, (list1, list2) -> list2.getValue() - list1.getValue());

		//获取前k个值
		int[] array = new int[k];
        for (int i=0; i<k; i++){
            array[i] = list.get(i).getKey();
        }
        return array;
	}
}

3. LC215.数组中的第k个最大元素

题目链接

用优先级队列方法做。
PriorityQueue,peek()方法返回的是堆顶元素,poll()方法移除的也是堆顶元素,offer()方法把元素插入队列末尾,队列会根据自定义实现排序。
所以我们考虑使用大顶堆还是小顶堆呢?
因为poll和peak针对的是堆顶元素,所以我们每次新来一个元素若想加入堆,都必须要移除堆顶的元素。如果是大顶堆的话,堆顶是最大的元素,但显然最大的元素不能被移除。所以我们要用小顶堆。若新来的元素比堆顶的大,则移除堆顶元素,把新元素加入进来。这样可以实现最后得到的大顶堆是前k个最大元素。堆顶就是第k个最大元素

代码
注意:

  1. 优先级队列的定义,还是要熟悉,尤其是里面的comparator怎么写
  2. 只有当新元素大于堆顶,而非大于等于时,才将新元素加入进来。比如考虑655,5是第二大元素,无论哪个5都是第二大元素,但如果两个5都加到堆里来的话,那堆里就有三个元素了,就成前3大元素了。所以加入堆的条件不能是等于。
  3. 基本类型转包装类,包装类转基本类型,必须熟记。
class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){
            public int compare(Integer a, Integer b){
                return a.intValue() - b.intValue();
            }
        });
        int index = 0;
        for (int i: nums){
            if (index < k){
                queue.offer(Integer.valueOf(i));
            }
            else{
                if (i > queue.peek()){
                    queue.poll();
                    queue.offer(Integer.valueOf(i));
                }
            }
            index++;

        }

        return queue.peek();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/443526.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入解析汽车MCU的软件架构

一、背景知识 电动汽车&#xff08;EV&#xff09;正在成为首选的交通方式&#xff0c;为传统内燃机汽车提供了一种可持续发展的环保型替代方案。在电动汽车复杂的生态系统中&#xff0c;众多电子控制单元&#xff08;ECU&#xff09;在确保其高效运行方面发挥着至关重要的作用…

HashSet在添加元素时,是如何判断元素重复的?

前言&#xff1a;我们知道Set中所存储的元素是不重复的&#xff0c;那么Set接口的实现类HashSet在添加元素时是怎么避免重复的呢&#xff1f; HashSet在添加元素时&#xff0c;是如何判断元素重复的? ● 在底层会先调用hashCode()&#xff0c;注意&#xff0c;Obje…

计算机系统

一、进制的转换 1.进制的表示 二进制&#xff08;B&#xff09;&#xff1a; 0&#xff0c;1&#xff0c;10 八进制&#xff08;O&#xff09;&#xff1a; 0&#xff0c;1&#xff0c;2&#xff0c;7&#xff0c;10&#xff0c;11 十进制&#xff08;D&#xff09;&#xff…

【c++】string模拟实现

string类的接口 namespace zjw {class string{public:typedef char* iterator;typedef const char* const_iterator;private:char* _str;int _size;int _capacity;};这里的迭代器直接使用原生指针来封装。 _str为指向string数组的首地址的指针。 _size为string数组的大小。 …

基于机器学习的网络入侵检测二元分类模型构建与性能评估(NSL-KDD数据集)

简介 该项目是一个基于NSL-KDD数据集的网络入侵检测系统&#xff0c;主要采用机器学习方法对网络流量数据进行使用了多种机器学习模型&#xff0c;如逻辑回归、线性SVM、多项式核SVM、高斯核SVM、决策树、随机森林、朴素贝叶斯和K近邻算法训练二元分类&#xff08;正常/异常&a…

漫谈技术成长

引言 相信很多程序员在自己的技术成长之路上&#xff0c;总会遇到许许多多的难关&#xff0c;有些难关咬咬牙就过去了&#xff0c;而有点难关则需要有一定的能力&#xff0c;才能克服。因此&#xff0c;本文主要围绕“技术成长” 话题&#xff0c;为何会选择技术方向&#xff0…

数据结构从入门到精通——队列

队列 前言一、队列1.1队列的概念及结构1.2队列的实现1.3队列的实现1.4扩展 二、队列面试题三、队列的具体实现代码Queue.hQueue.ctest.c队列的初始化队列的销毁入队列出队列返回队头元素返回队尾元素检测队列是否为空检测元素个数 前言 队列是一种特殊的线性数据结构&#xff…

练习ROS动作编程

ROS学习记录&#xff1a;动作编程 引言&#xff1a; ​ 通过本实验&#xff0c;我们将联系我们学过的动作编程&#xff0c;客户端发送一个运动目标,模拟小乌龟运动到目标位置的过程,包含服务端和客户端的代码实现&#xff0c;并且带有实时的位置反馈。 希望你在本次学习过后&am…

计算机网络谢希仁第8版课后习题答案(PDF)

百度网盘&#xff1a;https://pan.baidu.com/s/1cY_DkwaljjL7kU00-APLhw 提取码&#xff1a;5488

linux网络通信(TCP)

TCP通信 1.socket----->第一个socket 失败-1&#xff0c;错误码 参数类型很多&#xff0c;man查看 2.connect 由于s_addr需要一个32位的数&#xff0c;使用下面函数将点分十进制字符串ip地址以网络字节序转换成32字节数值 同理端口号也有一个转换函数 我们的端口号位两个字…

Spring boot 请求参数包含[]等特殊字符,导致无法接收问题

前言对字符进行转义修改tomcat 配置 前言 Spring boot 请求参数包含[]等特殊字符&#xff0c;导致无法接收问题 对字符进行转义 中括号[] 必须用%5B%5D转义&#xff0c;否则tomcat无法解析&#xff0c;回抛出不合法字符异常&#xff0c;不会进入控制器 修改tomcat 配置 p…

Kubernetes 安全秘籍:5 个你必须知道的知识点

Kubernetes 安全和身份验证是确保集群和应用安全的关键。今天将深入探讨 Service Account、身份验证和RBAC的关键概念和实践&#xff0c;帮助您构建安全可靠的应用。今天本文将着重于安全相关的内容&#xff0c;并提供更详细的示例和配置说明&#xff0c;帮助兄弟们更深入地理解…

Java8 CompletableFuture异步编程-进阶篇

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前言 我们在前面文章讲解了CompletableFuture这个异步编程类的基本用法&#xff0c;…

猫头虎分享已解决Bug || 系统监控故障:MonitoringServiceDown, MetricsCollectionError

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【敬伟ps教程】文字处理工具

文章目录 文字工具使用方式文字图层文字工具选项字符面板段落面板文字工具使用方式 文字工具(快捷键T),包含横排和直排两种类型 创建文本两种类型:点式文本、段落文本 创建文字方式 1、在画面上单击,出现文字光标,可输入文字,然后需要在工具栏中点击“√”或者 Ctrl+…

存算一体成为突破算力瓶颈的关键技术?

大模型的训练和推理需要高性能的算力支持。以ChatGPT为例&#xff0c;据估算&#xff0c;在训练方面&#xff0c;1746亿参数的GPT-3模型大约需要375-625台8卡DGX A100服务器训练10天左右&#xff0c;对应A100 GPU数量约3000-5000张。 在推理方面&#xff0c;如果以A100 GPU单卡…

UnityShader——09数学知识3

方阵 行与列数量相等的矩阵,n*n阶矩阵 对角矩阵 当对角线以外的矩阵内元素全为0&#xff0c;则称之为对角矩阵&#xff0c;对角矩阵的前提是必须是方阵 单位矩阵 对角线元素全为1&#xff0c;其余元素全为0&#xff0c;属于对角矩阵的一部分 矩阵和向量 把1 * n阶矩阵称…

JavaWeb - 2 - HTML、CSS

什么是HTML、CSS&#xff1f; HTML&#xff08;HyperText Markup Language&#xff09;&#xff1a;超文本标记语言 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大&#xff0c;除了文字信息&#xff0c;还可以定义图片、音频、视频等内容 标记语言&…

ESP8266程序烧录方法(以ESPFlashDownloadTool为例)

0 工具准备 ESP8266必须包含的目标bin ESPFlashDownloadTool_v3.6.3.exe NodeMCU&#xff08;ESP8266&#xff09; sscom5 1 ESP8266程序烧录方法&#xff08;以ESPFlashDownloadTool为例&#xff09; 1.1 生成ESP8266所需的bin文件 可以参考前面所写的《安信可IDE&#xff0…

被唤醒的“第二十条”深入人心

近来张艺谋执导的电影《第二十条》&#xff0c;因为它与正在召开中的全国两会所发布的《最高人民法院工作报告》联系相当紧密&#xff0c;加之可免费收看&#xff0c;网民便相互转告&#xff0c;于是此信息条目立即冲上了网络热搜榜&#xff0c;观者如潮。因为最高人民法院工作…