day9 | 栈与队列 part-1 (Go) | 232 用栈实现队列、225 用队列实现栈

今日任务 

  • 栈与队列的理论基础 (介绍:代码随想录)
  • 232 用栈实现队列(题目:  . - 力扣(LeetCode))
  • 225 用队列实现栈 (题目: . - 力扣(LeetCode) )

栈与队列的理论基础

        栈 : 先进后出    队列: 后进先出

        老师给的讲解:代码随想录   这个可能适合于 c++的同学理解,我的 go 看这里是有点不明所以..


232 用栈实现队列

        请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

想法:

        其实我完全理解栈与队列的特性, 先进后出、先进先出嘛, 但是一开始明白这题让干嘛的,在想这是否跟语言有关啊? 下一步直接看题解Go代码,

问题:

        看了题解才明白,其实我们就是可以利用各种语言提供的数据类型, 去模拟实现栈的一个效果,栈就是要具有 push 、pop、top、empty 这几个操作.  然后再用栈去实现 队列的操作:push、pop、peek、empty.

        那么理解了题意后,才是该思考的问题了,如何用拥有栈特性的数据结构去实现拥有队列属性的数据结构呢??🤔🤔

解决思路:

        使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。       

        就是我们将数据 push 到栈里了,这时该如何将第一个 push 到栈的数据通过 pop给先取出来呢? 我们可以借助另一个栈2,将我们另一个栈的数据 全取出来,再 push 到栈 2 里了,这时的栈 2 的元素出栈的顺序就和我们的队列相同了.

        

图片和题解参考:代码随想录

 看代码(Go):

// 先用切片模拟栈,再用两个栈的特性去模拟一个队列的特性
//  1、通过切片实现一个栈的各种操作
type MyStack []int

func (s *MyStack) Push(v int){
    *s = append(*s,v)
}

func (s *MyStack) Pop() int {
    val := (*s)[len(*s)-1]
    *s = (*s)[:len(*s)-1]
    return val
}

func (s *MyStack) Peek() int {
    val := (*s)[len(*s)-1]
    return val
}

func (s *MyStack) Size() int {
    return len(*s)
}

func (s *MyStack) Empty() bool{
    return s.Size() == 0
}


// 2、下面开始用两个栈实现队列
type MyQueue struct {
    inStack *MyStack
    outStack *MyStack
}


func Constructor() MyQueue {
    return MyQueue {
        inStack: &MyStack{},
        outStack: &MyStack{},
    }
}


func (this *MyQueue) Push(x int)  {
    this.inStack.Push(x)
}

// 在取之前,要先把入栈里的元素全都取出放到出栈里(如果出栈里仍有数据的话,肯定还是可以直接出的)
func (this *MyQueue) Pop() int {
    this.moveStack()
    return this.outStack.Pop()
}


func (this *MyQueue) Peek() int {
    this.moveStack()
    return this.outStack.Peek()
}


func (this *MyQueue) Empty() bool {
    return this.inStack.Empty() && this.outStack.Empty()
}

func (this *MyQueue) moveStack() {
    // 如果出栈为空的时候,再将入栈里的数据全都移动到出栈里,这样保证所有数据一直按照先进先出的顺序来的
    if this.outStack.Empty() {
        for !this.inStack.Empty() {
            this.outStack.Push(this.inStack.Pop())
        }
    }
}

225 用队列实现栈

        请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

想法:

        做了上一题后,我们就明白该如何去用语言已有的数据结构去模拟出栈的操作,我直接用切片就能实现栈的操作哎,但是题目还是让我们用两个队列实现,主要还是想要我们理解其中该如何转换.

问题:

       两个队列该如何实现呢? 如果我们像上一题,一个输入一个输出队列模拟还真不行, 因为最后出来的还都是先进先出.

解决思路:

1、两个队列 (题目要求)

        依然还是要用两个队列来模拟栈,只不过没有输入和输出的关系,而是另一个队列完全用来备份的!如下面动画所示,用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1.

2、一个队列 (更优)

        一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。

        

 图片和题解参考:代码随想录 

// 使用1个 队列实现栈的效果
 type MyStack struct{  // 初始化
    queue []int
 }

 func Constructor() MyStack {
    return MyStack{
        queue: make([]int,0),
    }
 }


func (this *MyStack) Push(x int){
    // 添加元素
    this.queue = append(this.queue,x)
}

func (this *MyStack) Pop() int {
    // 取出元素,因为我们当前是模拟在队列里的,遵守了一个先进先出的顺序,那么为了实现栈,我们要实现后进先出的效果
    n := len(this.queue)-1  // 判断长度
    // 除了最后一个元素,其余的都重新添加到队列里
    for n != 0{
        val := this.queue[0]
        // 截掉第一个元素,即将加入到队尾
        this.queue=this.queue[1:]
        this.queue=append(this.queue,val)
        n--
    }
    // 弹出元素
    val := this.queue[0]
    this.queue = this.queue[1:]
    return val
}

func (this *MyStack) Top() int {
    val := this.Pop()
    // 先弹出来,再添加进去,虽然这个过程也挺无语的,就是先来了个 for 循环把最后一个元素取出来了,然后再推进去.
    this.Push(val)
    return val
}

func (this *MyStack) Empty() bool {
    return len(this.queue) == 0
}




// 两个队列实现的
type MyStack struct {
    //创建两个队列
    queue1 []int
    queue2 []int
}


func Constructor() MyStack {
    return MyStack{	//初始化
        queue1:make([]int,0),
        queue2:make([]int,0),
    }
}


func (this *MyStack) Push(x int)  {
     //先将数据存在queue2中
    this.queue2 = append(this.queue2,x)	
   //将queue1中所有元素移到queue2中,再将两个队列进行交换
    this.Move() 
}


func (this *MyStack) Move(){    
    if len(this.queue1) == 0{
        //交换,queue1置为queue2,queue2置为空
        this.queue1,this.queue2 = this.queue2,this.queue1
    }else{
        //queue1元素从头开始一个一个追加到queue2中
            this.queue2 = append(this.queue2,this.queue1[0])  
            this.queue1 = this.queue1[1:]	//去除第一个元素
            this.Move()     //重复
    }
}

func (this *MyStack) Pop() int {
    val := this.queue1[0]
    this.queue1 = this.queue1[1:]	//去除第一个元素
    return val

}


func (this *MyStack) Top() int {
    return this.queue1[0]	//直接返回
}


func (this *MyStack) Empty() bool {
return len(this.queue1) == 0
}

我这一开始提交的可以直接通过,但是不是队列实现栈,哈哈...

// 我这下面的栈并不是由队列实现的?  感觉有点奇怪,直接就用了下标索引取值的很 easy
type MyStack struct {
    queue []int
}


func Constructor() MyStack {
    return MyStack{
        queue: make([]int,0),
    }
}


func (this *MyStack) Push(x int)  {
    this.queue = append(this.queue,x)
}


func (this *MyStack) Pop() int {
    val := this.queue[len(this.queue) - 1]
    this.queue = this.queue[0:len(this.queue)-1]
    return val
}


func (this *MyStack) Top() int {
    return this.queue[len(this.queue) - 1]
}


func (this *MyStack) Empty() bool {
    return len(this.queue) == 0
}

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

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

相关文章

left join limit offset 分页查询问题

1. LEFT JOIN 简介 在开始讨论LEFT JOIN的使用方法之前,让我们先简要回顾一下LEFT JOIN的概念。 LEFT JOIN是一种用于将左表和右表连接起来的操作。它会返回左表中的所有记录,并且对于每条左表记录,如果在右表中找到符合条件的记录&#xf…

js+网络摄像头实现人体肢体关键点动作捕获

最近有一个项目,客户需要用户人体姿势识别,进行表演考核用途,或者康复中心用户恢复护理考核,需要用摄像头进行人体四肢进行肢体关键点对比考核,资料还是太少了。只有个别大佬发了部分技术指导。感觉写的不错。 阿里云…

算法第四十一天-排除排序链表中的重复元素Ⅱ

排除排序链表中的重复元素Ⅱ 题目要求 解题思路 题意:在一个有序链表中,如果一个节点的值出现不止一次,那么把这个节点删除掉 重点:有序链表,所以,一个节点的值出现不止一次,那么他们必相邻。…

CMC学习系列 (7):β 范围 EEG-EMG 相干性与皮质光谱功率有关

CMC学习系列:β 范围 EEG-EMG 相干性与皮质光谱功率有关 0. 引言1. 主要贡献2. 方法2.1 目标2.2 实验范式2.3 数据处理和分析 3. 结果4. 讨论5. 总结欢迎来稿 论文地址:https://www.sciencedirect.com/science/article/abs/pii/S1053811907001760 论文题目&#xff…

一、接口自动化之pytest 运行参数

1、在跟目录下创建一个配置项pytest.ini [pytest] testpaths./testcases markersp0:高于优先级test:测试环境pro:生成环境2、打标签 3、运行命名pytest -m "p0"

单链表详解(无哨兵位),实现增删改查

1.顺序表对比单链表的缺点 中间或头部插入时,需要移动数据再插入,如果数据庞大会导致效率降低每次增容就需要申请空间,而且需要拷贝数据,释放旧空间增容造成浪费,因为一般都是以2倍增容 2.链表的基础知识 链表也是线…

蓝桥杯 — — 数数

数数 友情链接:数数 题目: 思路: 这道题目主要用到了埃氏筛法(Sieve of Eratosthenes)来快速求解质数的方法,思路很巧妙,并且用到了动态规划的思想。 我们首先定义两个数组mk和p&#xff0c…

LPA3399Pro搭建Qt开发环境

将以前的开发文档在此做一个记录。 一、介绍 Qt是一个跨平台的应用程序开发框架,支持多种操作系统和硬件架构,包括ARM架构的Linux。 RK3399Pro是一款基于ARM架构的处理器,用于嵌入式系统。可以在RK3399上搭建Qt开发环境,进行项目…

C语言学习笔记之结构体(一)

目录 什么是结构体? 结构体的声明 结构体变量的定义和初始化 结构体成员的访问 结构体传参 什么是结构体? 在现实生活中的很多事物无法用单一类型的变量就能描述清楚,如:描述一个学生,需要姓名,年龄&a…

演示:单包攻击,扫描类攻击,畸形报文攻击[Land攻击,泪滴攻击,ip地址欺骗]。配置防火墙进行防御

浏览上篇博客进行环境搭建 单包攻击 单包攻击(Single Packet Attack)是一种利用网络协议或应用程序中的漏洞进行的攻击方式。这种攻击通常只需要发送一个精心构造的数据包,就能够触发目标系统的漏洞,导致攻击者能够执行非授权的…

JVM修炼之路【12】- GC调优 、性能调优

上一篇中 我们详细讲了内存溢出 内存泄漏 还有相关的案例。 这篇博客中我们主要了解一下GC调优。 有些新手可能会有一点 疑问—— 这两者不是一回事吗?? 其实说一回事 也没错 因为GC调优本质上还是针对 堆上的内存 只不过前面我们关注的侧重点在于 不合…

关于机器学习中贝叶斯学习(Bayesian Learning)计算公式的理解

一、引言 在《统计学习的分类概述》中介绍了贝叶斯学习的概念和计算公式,可以看到这个公式就是概率统计理论中的贝叶斯公式,但在机器学习中这个公式与概率统计中的理解要复杂得多。 二、贝叶斯学习公式及各组成因子的含义 要理解贝叶斯学习公式&#…

【Spring Security】1.Spring Security介绍 功能介绍

文章目录 一、Spring Security介绍二、功能介绍 一、Spring Security介绍 官方文档:https://docs.spring.io/spring-security/reference/index.html 官网解释:Spring Security 是一个提供 身份验证、授权 和 针对常见攻击的保护 的框架。 它为 保护命令…

运放噪声评估的来龙去脉

运放噪声评估的来龙去脉 友情提示,运放电路的噪声分析还是比较复杂的,不论是基础理论还是对应的推导过程,都不是特别容易。考虑到兄弟们的基础参差不齐,所以我还是尽量说清楚点,这样导致看起来就有点罗里吧嗦&#xff…

刷题之动态规划-回文串

前言 大家好,我是jiantaoyab,开始刷动态规划的回文串类型相关的题目 动态规划5个步骤 状态表示 :dp数组中每一个下标对应值的含义是什么>dp[i]表示什么状态转移方程: dp[i] 等于什么1 和 2 是动态规划的核心步骤,…

市场复盘总结 20240412

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 二进三: 进级率 50% 最常用的二…

iOS开发之为什么需要引用计数

iOS开发之为什么需要引用计数 在iOS开发中,Objective-C与Swift语言都是通过引用计数进行内存管理,实际上Python、Ruby、C等语言也提供了基于引用计数的内存管理方式,它们有一个共同点,那就是都是面向对象的编程语言。 引用计数可…

响应式布局(其次)

响应式布局 一.响应式开发二.bootstrap前端开发框架1.原理2.优点3.版本问题4.使用(1)创建文件夹结构(2)创建html骨架结构(3)引入相关样式(4)书写内容 5.布局容器(已经划分…

Cascader 级联选择器 - 选择器最后一级数据为空

原因:将扁平数据转化为树形数据时,给每个项都添加了 children export const transList2Tree (list, rootPid) > {const result []list.forEach(item > {if (item.pid rootPid) {const children transList2Tree(list, item.id)item.children …

c语言多功能计算软件170

定制魏:QTWZPW,获取更多源码等 目录 题目 要求 主要代码片段 题目 设计一个计算器软件,具备如下功能提示界面。 要求 设计出界面,注意界面名称最后为自己的姓名;(20分)能够实现加、减、乘、…