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

news2024/11/18 2:35:11

今日任务 

  • 栈与队列的理论基础 (介绍:代码随想录)
  • 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
}

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

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

相关文章

stm32f103---按键控制LED---代码学习

目录 一、总体代码 二、LED端口初始化分析 ​编辑 三、LED灭的控制 四、LED亮 五、按键初始化 ​ 六、按键控制LED的功能 一、总体代码 这里使用到了LED灯和按键,实现效果是当按键按下时灯的亮灭转化 #include "stm32f10x.h" #include "bsp_led…

Jupyter Notbook如何安装配置并结合内网穿透实现无公网IP远程连接使用

文章目录 推荐1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂&am…

《手把手教你》系列基础篇(八十五)-java+ selenium自动化测试-框架设计基础-TestNG自定义日志-下篇(详解教程)

1.简介 TestNG为日志记录和报告提供的不同选项。现在,宏哥讲解分享如何开始使用它们。首先,我们将编写一个示例程序,在该程序中我们将使用 ITestListener方法进行日志记录。 2.TestNG自定义日志 2.1创建测试用例类 1.按照宏哥前边的方法&…

TensorFlow中LSTM神经网络详解

TensorFlow中LSTM神经网络详解 一、LSTM神经元1.1 神经网络引入1.2 RNN神经元结构1.3 LSTM神经元1.3.1 LSTM模型框架1.3.2 隐藏态1.3.3 遗忘门1.3.4 记忆门1.3.5 输出门 二、LSTM神经网络2.1 LSTM网络架构 时间序列预测分析可以实现对未来数据的预测分析,通过分析过…

安装mamba_ssm报错

最近想跑一下VM-UNet的代码,结果发现需要安装mamba_ssm,于是我直接pip install mamba_ssm,发现报错,错误提示说需要安装cuda11.6及以上的版本。然后我就默默地安装cuda11.6,后来我才发现不用安装cuda11.6也可以。 在vmunet的gitu…

【笔记】mysql版本6以上时区问题

前言 最近在项目中发现数据库某个表的createTime字段的时间比中国时间少了13个小时,只是在数据库中查看显示时间不对,但是在页面,又是正常显示中国时区的时间。 排查 项目中数据库的驱动使用的是8.0.19,驱动类使用的是com.mysq…

快速入门深度学习9.1(用时20min)——GRU

速通《动手学深度学习》9.1 写在最前面九、现代循环神经网络9.1 门控循环单元(GRU)9.1.1. 门控隐状态9.1.1.1. 重置门和更新门9.1.1.2. 候选隐状态9.1.1.3. 隐状态 9.1.3 API简洁实现小结 🌈你好呀!我是 是Yu欸 🌌 20…

数据结构学习之路--一网打尽链表的相关操作(附C源码)

嗨嗨大家~我们今天继顺序表内容来讲解链表。话不多说,让我们走进本期的学习吧! 目录 一、线性表的链式存储 1 链式存储结构 2 链表的定义 3 链表的分类 二、链表的实现过程 1 链表的打印 2 结点的创建 3 链表的头插 4 链表的头删 5 链表的…

vue列表列表过滤

对已知的列表进行数据过滤(根据输入框里面的内容进行数据过滤) 编写案例 通过案例来演示说明 效果就是这样的 输入框是模糊查询 想要实现功能,其实就两大步,1获取输入框内容 2根据输入内容进行数据过滤 绑定收集数据 我们可以使用v-model去双向绑定 …

LazyVim开发vue2

neovim 0.5刚出来的时代,那时刚有lua插件我很狂热。每天沉迷于打造自己的IDE之中。写过一堆相关的博客,也录过一些视频教程。后来发现neovim的接口和插件更新的很快,导致配置文件要不定期的修改,才能保证新版本的插件的适配。我也…

深入理解DES算法:原理、实现与应用

title: 深入理解DES算法:原理、实现与应用 date: 2024/4/14 21:30:21 updated: 2024/4/14 21:30:21 tags: DES加密对称加密分组密码密钥管理S盒P盒安全性分析替代算法 DES算法简介 历史 DES(Data Encryption Standard)算法是由IBM研发&…

llamafactory:unified efficient fine-tuning of 100+ lanuage models

1.introduction llamafactory由三个主要模块组成,Model Loader,Data Worker,Trainer。 2.Efficient fine-tuning techniques 2.1 Efficient Optimization 冻结微调:冻结大部分参数,同时只在一小部分解码器层中微调剩…

Python怎么算平方

Python怎么算平方?下面是算平方的三种方法: 方法一:使用内置模块 >>> import math >>> math.pow(12, 2) # 求平方 144.0 方法二:使用表达式 >>> 12 ** 2 # 求平方 144 方法三&#…

量子城域网系列(三):搭建一个点对点量子保密通信网络

各位小伙伴周末愉快呀,今天是4月14日世界量子日,至于为今天是世界量子日可以围观我之前的文章:关于世界量子日。 之前的文章中我们讨论了量子密钥在通信系统各层协议中的应用,那在实际工程中如何真正落地一个量子加密网络呢&a…

minikube环境搭建

📕作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📘相关专栏Rust初阶教程、go语言基础系列、spring教程等,大家有兴趣的可以看一看 📙Jav…

Jmeter杂记:测试计划参数详解

测试计划各参数详解 1,用户自定义变量,是全局变量,供所有线程组使用,可用配置元件:用户自定义变量替代 2,连续的运行线程组,默认不勾选,则随机的运行多个线程组中的取样器&#xff…

什么是享元模式,有哪些具体应用

一、定义 享元模式是一种通过尽可能多地共享数据来最小化内存使用和对象数量,从而提高性能的设计模式。在享元模式中,如果需要相同数据的多个对象,则共享这些对象而不是创建新的对象,从而提高系统的效率。 其实有很多应用场景&am…

spring-cloud-alibaba微服务Sentinel

Sentinel 官方网站 sentinel-dashboard-1.8.7.jar包下载地址 在window通过命令行启动(java -Dserver.port8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.7.jar),可以通过 -Dserver.port修改控制台的端口 使用的版本最好…

vue--双向数据绑定原理

Vue采用数据劫持 发布者-订阅者模式实现双向数据绑定,实现逻辑图如下所示: 数据劫持 Vue 借助Object.defineProperty()来劫持各个属性,这样一来属性存取过程都会被监听到 发布者-订阅者模式 主要实现三个对象:Observer&#…

docker 安装 nginx + httpd + php-fpm

原文地址:http://www.taoluyuan.com/index.php/archives/30/#2 展示 1.安装 1.1安装docker 1.2安装nginx 1.3安装apache-httpd 1.4安装php-fpm 2.配置nginx反向代理 httpdphp-fmp 1.安装 1.1安装docker 移除旧的版本: sudo yum remove docker 安装…