好题分享(2023.11.12——2023.11.18)

目录

前情回顾:

 前言:

题目一:《有效括号》

思路:

总结:

题目二:《用队列实现栈》

思路:

总结:

题目三:《用栈实现队列》 

思路:

总结 :

总结:


 

 

前情回顾:

我们在上一篇好题分析中,分析了以下几题:

《反转链表》《相交链表》《环形链表(一)》《环形链表(二)》《随机链表的复制》《合并两个有序链表》

《链表中倒数第K个节点》《链表分割》《链表的回文结构》

上一篇的好题分析的blog:

好题分享(2023.11.5——2023.11.11)-CSDN博客

 前言:

本次《好题分享》当中,我们主要熟悉我们刚刚所学的《栈和队列》这一部分内容。

通过三道Leecode题目使我们对于《栈和队列》能有一个更好的认识。

以下是我们需要解决的三道题目:

《有效括号》《用队列实现栈》《用栈实现队列》

 这三道题的代码量都会非常的长,那是由于我们现在处于初学阶段,没有办法使用一些高效的方法来解决这些题目,但是不用怕,因为我们不仅仅实现过《栈》也实现过《队列》。

对于《栈和队列》的讲解可以去访问我的上一篇blog

《栈和队列》的模拟实现(顺序栈) (链队列)-CSDN博客

里面有需要实现本次题目的代码,打开我的Gitee即可获取。

在做题目之前我们首先需要将我们实现好的《栈》或者《队列》的代码粘贴到题目最前面的位置。

那么现在我们就来动手实践以及讲解 


题目一:《有效括号》

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

 

typedef char STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;void STInit(ST* pst)
{pst->a = NULL;pst->capacity = 0;pst->top = -1;
}void STDestory(ST* pst)
{assert(pst);free(pst);pst = NULL;
}void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top || pst->top == -1){int newCapacity = (pst->capacity == 0) ? 4 : 2 * (pst->capacity);STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(ST)*newCapacity);if (tmp == NULL){perror("STPush -> realloc");exit(-1);}pst->a = tmp;pst->capacity = newCapacity;}pst->top++;pst->a[pst->top] = x;
}void STPop(ST* pst)
{assert(pst);pst->top--;
}STDataType STTop(ST* pst)
{assert(pst);return pst->a[pst->top];
}bool STEmpty(ST* pst)
{assert(pst);if (pst->top == -1){return true;}return false;
}int STSize(ST* pst)
{assert(pst);return (pst->top) + 1;
}void STPrint(ST* pst)
{assert(pst);while (pst->top != -1){printf("%d\n", STTop(pst));STPop(pst);}
}bool isValid(char* s) {ST st;STInit(&st);while(*s){if(*s == '[' || *s == '(' || *s == '{'){STPush(&st,*s);}else{if(STEmpty(&st)){return false;}else{char top = STTop(&st);STPop(&st);if((top == '(' && *s != ')')||(top == '{' && *s != '}')|| (top == '[' && *s != ']')){return false;}}}s++;}if(!STEmpty(&st)){return false;}return true;}

思路:

 

本题的思路就是利用《栈》的性质——先进后出

因为是匹配括号,我们不妨假设其本质就是一个《栈》。

我们先去遍历字符串,如果访问到左括号,例如

"{"                   "("                "["

就直接入栈。

而如果访问到右括号,我们就与栈顶的括号匹配,如果左右括号匹配成功就删除栈顶的括号,字符串继续遍历,直到遍历完成。

如图:

 

 

 栈顶的括号与s指向的括号相匹配

 

此时相匹配,则删除栈顶元素:

 

如此继续遍历。

 

此时s指向'\0'代表遍历结束,而如果《栈》为空,就代表着字符串为有效括号,就可以return true

总结:

1.创建《栈》

2.遍历字符串,左括号入《栈》

3.遍历到右括号,则于《栈》顶的左括号相匹配

4.当字符串遍历完后,《栈》为空则return true;

但是这里存在一个细节,需要去注意

例如,如果我们在遍历字符串时遍历到有括号时,可是《栈》中没有栈顶元素与之匹配,则直接返回false。

 

题目二:《用队列实现栈》

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

 

typedef int QDataType;typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int sz;
}Queue;void QueueInit(Queue* pq)
{pq->sz = 0;pq->phead = pq->ptail = NULL;
}void QueueDestroy(Queue* pq)
{assert(pq);assert(pq->phead);QNode* cur = pq->phead->next;while (cur){free(pq->phead);pq->phead = cur;cur = cur->next;}free(pq->phead);pq->phead = pq->ptail = cur = NULL;}void QueuePop(Queue* pq)
{assert(pq);if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* tmp = pq->phead->next;free(pq->phead);pq->phead = tmp;}pq->sz--;
}void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("QueuePush -> malloc");exit(-1);}newnode->val = x;newnode->next = NULL;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->sz++;
}QDataType QueueFront(Queue* pq)
{assert(pq);return pq->phead->val;
}QDataType QueueBack(Queue* pq)
{assert(pq);return pq->ptail->val;
}bool QueueEmpty(Queue* pq)
{assert(pq);if (pq->phead == NULL){return true;}return false;
}int QueueSize(Queue* pq)
{return pq->sz;
}void QueuePrint(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){printf("%d->", cur->val);cur = cur->next;}printf("NULL\n");
}typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* pst = (MyStack*)malloc(sizeof(MyStack));QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}void myStackPush(MyStack* obj, int x) {if (QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2)){QueuePush(&obj->q1, x);}else{if (!QueueEmpty(&obj->q1)){QueuePush(&obj->q1, x);}else{QueuePush(&obj->q2, x);}}
}int myStackPop(MyStack* obj) {if (QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2)){return 0;}else{if (!QueueEmpty(&obj->q1)){int n = QueueSize(&obj->q1) - 1;while (n){int top = QueueFront(&obj->q1);QueuePush(&obj->q2, top);QueuePop(&obj->q1);n--;}int top = QueueFront(&obj->q1);QueuePop(&obj->q1);return top;}else{int n = QueueSize(&obj->q2) - 1;while (n){int top = QueueFront(&obj->q2);QueuePush(&obj->q1, top);QueuePop(&obj->q2);n--;}int top = QueueFront(&obj->q2);QueuePop(&obj->q2);return top;}}
}int myStackTop(MyStack* obj) {if (QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2)){return 0;}else{if (!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}}
}bool myStackEmpty(MyStack* obj) {if (!QueueEmpty(&obj->q1) || !QueueEmpty(&obj->q2)){return false;}return true;}void myStackFree(MyStack* obj) {if (!QueueEmpty(&obj->q1) && !QueueEmpty(&obj->q2)){if (!QueueEmpty(&obj->q1)){QueueDestroy(&obj->q1);}else{QueueDestroy(&obj->q2);}}
}/*** Your MyStack struct will be instantiated and called as such:* MyStack* obj = myStackCreate();* myStackPush(obj, x);* int param_2 = myStackPop(obj);* int param_3 = myStackTop(obj);* bool param_4 = myStackEmpty(obj);* myStackFree(obj);
*/

该题目的代码量会非常长,刚开始做题时是会产生恐惧,但是不用害怕,因只要我们了解了其中代码的秘密,我们就能迎刃而解了。

思路:

 由题意,就是让我们创建两个栈,然后通过两个栈之间的操作,完成一个队列的基本实现。

我们想要插入12345,那么对于栈来说

1就是《栈》底元素,5就是《栈》顶元素。

出栈也只能出5

但是对于队列而言呢?

队头是1,队尾是5

出队列也只能出1.

所以对于“出栈”就可以利用两个队列:

先让12345插入到队列1,即q1

再让q1中的各个元素一个个的进到队列q2中

 

 

如此不断循环

直到q1只剩一个元素,那个元素就是对应的“栈顶”。

我们将这个元素删除即可:

 

 

 最后则返回top:

以上就是“出栈”的函数实现,那么对于入栈来说,就是哪个队列不为空就插入到哪个队列中。

具体的代码还是好实现的。后续的函数我也不做过多的赘述。

总结:

对于这道题我们讲解关于“出栈”函数的实现就可以解决大部分问题。

但是这道题的自定义数据类型可能会有人绕不清楚,接下来我画一张图大家就可以理解了:

 

我们在上一篇blog也讲过,创建一个结构体用来保存头指针和尾指针对象,可以大大提高传输效率,也可以使人理解透彻!

 

题目三:《用栈实现队列》 

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;void STInit(ST* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;pst->top = -1;
}void STDestory(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = -1;pst->capacity = 0;
}void STPush(ST* pst, STDataType x)
{assert(pst);int newcapacity = (pst->capacity == 0) ? 4 : 2 * (pst->capacity);STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("STPush -> realloc");exit(-1);}pst->a = tmp;pst->capacity = newcapacity;pst->top++;pst->a[pst->top] = x;}void STPop(ST* pst)
{assert(pst);if (pst->top != -1){pst->top--;}
}STDataType STTop(ST* pst)
{assert(pst);if (pst->top != -1){return pst->a[pst->top];}return -1;
}bool STEmpty(ST* pst)
{assert(pst);if (pst->top == -1){return true;}return false;
}int STSize(ST* pst)
{assert(pst);return pst->top + 1;
}void STPrint(ST* pst)
{assert(pst);for (int i = 0; i <= pst->top; i++){printf("%d  ", pst->a[i]);}
}typedef struct {ST SPush;ST SPop;
} MyQueue;MyQueue* myQueueCreate() {MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->SPush);STInit(&obj->SPop);return obj;
}void myQueuePush(MyQueue* obj, int x) {STPush(&obj->SPush,x);
}int myQueuePop(MyQueue* obj) {int front = myQueuePeek(obj);STPop(&obj->SPop);return front;
}int myQueuePeek(MyQueue* obj) {if(STEmpty(&obj->SPop)){while(!STEmpty(&obj->SPush)){STPush(&obj->SPop,STTop(&obj->SPush));STPop(&obj->SPush);}}return STTop(&obj->SPop);
}bool myQueueEmpty(MyQueue* obj) {if(STEmpty(&obj->SPush) && STEmpty(&obj->SPop)){return true;}return false;
}void myQueueFree(MyQueue* obj) {STDestory(&obj->SPop);STDestory(&obj->SPush);free(obj);
}/*** Your MyQueue struct will be instantiated and called as such:* MyQueue* obj = myQueueCreate();* myQueuePush(obj, x);* int param_2 = myQueuePop(obj);* int param_3 = myQueuePeek(obj);* bool param_4 = myQueueEmpty(obj);* myQueueFree(obj);
*/

本题的代码与上题一样,先将实现栈的函数粘贴到该题目中。

思路:

 我们还是先来讲讲“出队列”这个思路。

“出队列”秉持一个原则,就是先进先出

而出缺是后进先出,所以我们不得不继续用到两个栈。

但是这里我们不同于上一道题,我们必须定义两个栈

即一个栈只能入数据,一个栈是用来出数据的。

 比如我还是将12345入栈。

如果是队列的话,只能实现先进先出,即将1删除。

所以我们可以借鉴上题那样,先将SPush里面的所以元素移到SPop中 :

这样一来,我们只需要删除SPop的栈顶元素即可。

如果我们想要继续输入数据,也不需要将SPop里面的数据再倒入SPush中,只需要再SPush里面继续添加新数据。

反正,只要SPop这个栈里有数据,就先删除栈顶的,而对于添加数据,只需要向SPush里面添加即可。

 

当删完SPop后如果还想删数据,则继续将SPush里面的数据倒入SPop即可。

 

总结 :

当然还是会有人对数据类型不是很理解,我还是画个图给大家观看:

 

 

总结:

 本文主要以巩固《栈和队列》为主,从此以后的好题分析,我们主要给大家讲解最关键思路,以及部分重难点函数的实现。

同学们下来可以自己动手尝试编写编写。

记住

“坐而言不如起而行!”

Aciton speak louder than words!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF实战项目十五(客户端):RestSharp的使用

1、在WPF项目中添加Nuget包&#xff0c;搜索RestSharp安装 2、新建Service文件夹&#xff0c;新建基础通用请求类BaseRequest.cs public class BaseRequest{public Method Method { get; set; }public string Route { get; set; }public string ContenType { get; set; } &quo…

Node.js之http模块

http模块是什么&#xff1f; http 模块是 Node,js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的 http.createServer() 方法&#xff0c;就能方便的把一台普通的电脑&#xff0c;变成一台Web 服务器&#xff0c;从而对外提供 Web 资源服务。 如果我们想在node…

Request 爬虫的 SSL 连接问题深度解析

SSL 连接简介 SSL&#xff08;Secure Sockets Layer&#xff09;是一种用于确保网络通信安全性的加密协议&#xff0c;广泛应用于互联网上的数据传输。在数据爬取过程中&#xff0c;爬虫需要与使用 HTTPS 协议的网站进行通信&#xff0c;这就牵涉到了 SSL 连接。本文将深入研究…

向日葵x华测导航:远程控制如何助力导航测绘设备运维

导航测绘在各个领域均在发挥积极作用&#xff0c;其中RTK载波相位差分技术是导航测绘领域所常用的主流技术&#xff0c;该技术基于卫星定位系统的基础定位数据&#xff0c;可以实现在野外实时获取厘米级精度的定位数据&#xff0c;一定程度上省去了事后解算的麻烦。相应的&…

(论文阅读46-50)图像描述2

46.文献阅读笔记 简介 题目 Learning a Recurrent Visual Representation for Image Caption Generation 作者 Xinlei Chen, C. Lawrence Zitnick, arXiv:1411.5654. 原文链接 http://www.cs.cmu.edu/~xinleic/papers/cvpr15_rnn.pdf 关键词 2014年rnn图像特征和文本特…

验证码 | 可视化一键管控各场景下的风险数据

目录 查看今日验证数据 查看未来趋势数据 验证码作为人机交互界面经常出现的关键要素&#xff0c;是身份核验、防范风险、数据反爬的重要组成部分&#xff0c;广泛应用网站、App上&#xff0c;在注册、登录、交易、交互等各类场景中发挥着巨大作用&#xff0c;具有真人识别、身…

Leo赠书活动-10期 【AIGC重塑教育 AI大模型驱动的教育变革与实践】文末送书

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

新手做抖店,这6点建议一定要收好,能让你不亏钱!

我是电商珠珠 我呢&#xff0c;目前身居郑州。 电商这个行业也做了5年多了&#xff0c;抖店从20年开始做&#xff0c;到现在也已经快3年了。 其实&#xff0c;我做抖店期间呢&#xff0c;踩过很多坑&#xff0c;所以今天就把我所踩过的坑&#xff0c;给做抖店的新手总结了6点…

QT mysql 数据库线程池 与数据库操作封装

最近事情比较多很久没有写学习笔记了&#xff0c;数据库线程池&#xff0c; 数据库封装&#xff0c;虽说数据库操作有很多不需要写sql 的&#xff0c;ORM 封装的方式去操作数据库。但是从业这些年一直是自己动手写sql &#xff0c;还是改不了这个习惯。不说了直接上代码。 数据…

【23真题】劝退211!今年突变3门课!

今天分享的是23年云南大学847&#xff08;原827&#xff09;的考研试题及解析。同时考SSDSP的院校做一个少一个&#xff0c;珍惜&#xff01;同时考三门课的院校&#xff0c;复习压力极大&#xff0c;但是也会帮大家劝退很多人&#xff0c;有利有弊&#xff0c;请自行分析~ 本…

YOLOv5 环境搭建

YOLOv5 环境搭建 flyfish 环境 Ubuntu20.04 驱动、CUDA Toolkit、cuDNN、PyTorch版本对应 1 NVIDIA驱动安装 在[附加驱动界]面安装驱动时&#xff0c;需要输入安全密码&#xff0c;需要记下&#xff0c;后面还需要输入这个密码 重启之后有的机器会出现 perform mok manage…

Android修行手册-溢出父布局的按钮实现点击

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

【EI会议征稿】第五届人工智能、网络与信息技术国际学术会议(AINIT 2024)

第五届人工智能、网络与信息技术国际学术会议&#xff08;AINIT 2024&#xff09; 2024 5th International Seminar on Artificial Intelligence, Networking and Information Technology 第五届人工智能、网络与信息技术国际学术会议&#xff08;AINIT 2024&#xff09;将于…

变态跳台阶,剑指offer

目录 题目&#xff1a; 我们直接看题解吧&#xff1a; 相似题目&#xff1a; 解题方法&#xff1a; 审题目事例提示&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 题目地址&#xff1a; 【剑指Offer】9、变态跳台阶 难度&#xff1a;简单 今天刷变态跳台阶&#xf…

sd-webui-controlnet代码分析

controlnet前向代码解析_Kun Li的博客-CSDN博客文章浏览阅读1.5k次。要分析下controlnet的yaml文件&#xff0c;在params中分成了4个部分&#xff0c;分别是control_stage_config、unnet_config、first_stage_config、cond_stage_config。其中control_stage_config对应的是13层…

Maven依赖管理项目构建工具(保姆级教学---下篇)

对于Maven依赖管理项目构建工具的介绍&#xff0c;我们将其分为上篇和下篇。如果您对文章感兴趣&#xff0c;您可以在此链接中找到上篇详细内容&#xff1a; Maven依赖管理项目构建工具&#xff08;保姆级教学上篇&#xff09;-CSDN博客 一、Maven依赖传递和依赖冲突 1. …

left join查询耗时太慢,添加索引解决问题

背景 因为最近自己用的小app越用感觉加载越慢&#xff0c;以为是自己app开发逻辑出现问题了&#xff0c;结果才发现是自己很早以前的代码用到的是left join多表联查&#xff0c;以前因为数据少&#xff0c;所以没有感觉&#xff0c;现在数据量稍微一大&#xff0c;耗时就非常严…

珠宝饰品配送经营小程序商城作用如何

饰品有较强的价值/品牌之分&#xff0c;贵的上万元&#xff0c;便宜的几毛钱&#xff0c;适应不同消费群体和需求&#xff0c;对于珠宝类商家及小饰品商家来说&#xff0c;市场中都有着海量用户。 相较于以前等客上门&#xff0c;用户们的消费方式只有同城&#xff0c;如今互联…

psutil - Python中用于进程和系统监控的跨平台库

1、简介 psutil&#xff08;进程和系统实用程序&#xff09;是一个跨平台库&#xff0c;用于检索 Python 中运行的进程和系统利用率&#xff08;CPU、内存、磁盘、网络、传感器&#xff09;的信息。 它主要用于系统监控、分析和限制进程资源以及管理正在运行的进程。 它实现…

我们对凌鲨的一次重构

在10月我们对凌鲨进行了一次重构&#xff0c;把所有鸡肋的功能都删除了。 新版本界面 老版本界面 我们干掉的功能 移除沟通频道功能 沟通频道类似slack功能&#xff0c;用于团队沟通。由于国内有大量的沟通软件&#xff0c;比如企业微信&#xff0c;飞书&#xff0c;钉钉等。…