首页 > 其他分享 >剑指 offer 09.用两个栈实现队列

剑指 offer 09.用两个栈实现队列

时间:2024-08-20 21:51:29浏览次数:18  
标签:deleteHead offer 队列 CQueue 09 top2 queue stack2 stack1

目录

原题链接

题目描述

题目样例

示例 1

输入

输出

示例 2

输入

输出

解决方案

核心思路

两个栈的作用

操作细节

代码解答

复杂度分析

总结

其他相似题目


原题链接

剑指offer_在线编程_牛客网 (nowcoder.com)

题目描述

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTaildeleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

  • 1 <= values <= 10000
  • 最多会对 appendTaildeleteHead 进行 10000 次调用

题目样例

示例 1

输入
  • ["CQueue","appendTail","deleteHead","deleteHead"]
  • [[],[3],[],[]]
输出
[null,null,3,-1]

示例 2

输入
  • ["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
  • [[],[],[5],[2],[],[]]
输出
[null,-1,null,null,5,2]

解决方案

核心思路

  • 是一种后进先出(LIFO, Last In First Out)的数据结构,而队列是一种先进先出(FIFO, First In First Out)的数据结构。
  • 通过使用两个栈,我们可以将栈的“后进先出”特性转化为队列的“先进先出”特性。

两个栈的作用

  • 栈1stack1):用于插入操作 (appendTail)。
  • 栈2stack2):用于删除操作 (deleteHead)。

操作细节

  1. appendTail(插入操作):每次插入时,直接将元素压入stack1中。
  2. deleteHead(删除操作)
  • 如果stack2为空:将stack1中的所有元素依次弹出并压入stack2中,再从stack2弹出栈顶元素作为要删除的元素。
  • 如果stack2不为空:直接从stack2弹出栈顶元素。
  • 这样,当从stack2弹出元素时,正好是队列的最前面的元素,实现了队列的FIFO特性。
  • 如果stack1stack2都为空,返回-1。

代码解答

python语言:

class CQueue:
    def __init__(self):
        self.stack1 = []  # 用于插入的栈
        self.stack2 = []  # 用于删除的栈

    def appendTail(self, value: int) -> None:
        self.stack1.append(value)

    def deleteHead(self) -> int:
        if not self.stack2:
            while self.stack1:
                self.stack2.append(self.stack1.pop())
        if not self.stack2:
            return -1
        else:
            return self.stack2.pop()

C语言:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct StackNode {
    int data;
    struct StackNode* next;
} StackNode;

typedef struct {
    StackNode* top1;
    StackNode* top2;
} CQueue;

CQueue* newCQueue() {
    CQueue* queue = (CQueue*)malloc(sizeof(CQueue));
    queue->top1 = NULL;
    queue->top2 = NULL;
    return queue;
}

void appendTail(CQueue* queue, int value) {
    StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
    newNode->data = value;
    newNode->next = queue->top1;
    queue->top1 = newNode;
}

int deleteHead(CQueue* queue) {
    if (queue->top2 == NULL) {
        while (queue->top1!= NULL) {
            StackNode* temp = queue->top1;
            queue->top1 = queue->top1->next;
            temp->next = queue->top2;
            queue->top2 = temp;
        }
    }
    if (queue->top2 == NULL) {
        return -1;
    } else {
        int value = queue->top2->data;
        StackNode* temp = queue->top2;
        queue->top2 = queue->top2->next;
        free(temp);
        return value;
    }
}

void freeQueue(CQueue* queue) {
    while (queue->top1!= NULL) {
        StackNode* temp = queue->top1;
        queue->top1 = queue->top1->next;
        free(temp);
    }
    while (queue->top2!= NULL) {
        StackNode* temp = queue->top2;
        queue->top2 = queue->top2->next;
        free(temp);
    }
    free(queue);
}

Java语言:

class CQueue {
    private java.util.Stack<Integer> stack1;
    private java.util.Stack<Integer> stack2;

    public CQueue() {
        stack1 = new java.util.Stack<>();
        stack2 = new java.util.Stack<>();
    }

    public void appendTail(int value) {
        stack1.push(value);
    }

    public int deleteHead() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.isEmpty()? -1 : stack2.pop();
    }
}

复杂度分析

  • 时间复杂度
    • appendTail:每次插入操作只涉及栈1的append操作,时间复杂度为O(1)。
    • deleteHead:最坏情况下,stack1中的所有元素都要搬到stack2,时间复杂度为O(n),但每个元素最多只会搬一次,因此摊销时间复杂度为O(1)。
  • 空间复杂度:O(n),其中n为存储在队列中的元素个数。

总结

通过两个栈的相互配合,我们可以实现队列的插入和删除操作,使得时间复杂度达到较优水平。这种设计有效地利用了栈的特性来模拟队列的行为。

其他相似题目

leetcode LCR 125.图书管理 Ⅱ

标签:deleteHead,offer,队列,CQueue,09,top2,queue,stack2,stack1
From: https://blog.csdn.net/LS_Ai/article/details/141368622

相关文章

  • 知识改变命运 数据结构【栈和队列】
    1.栈(Stack)1.1概念栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut)的原则。压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。出栈:栈的删......
  • OFtutorial09_runtimePostprocessingUtility解析
    组成pipeCalc.H源码头文件#ifndefpipeCalc_H#definepipeCalc_H#include"volFieldsFwd.H"#include"Switch.H"#include"fvc.H"#include"fvMeshFunctionObject.H"#include"logFiles.H"#include"addToRunTi......
  • 【数据结构】栈和队列的实现
    正文1.栈1.1概念与结构栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut)的原则。压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,⼊数据在栈顶......
  • 数据结构-队列 c语言使用链表和数组分别实现
    队列定义队列(queue)是一种遵循先入后到规则的线性数据结构,将队列头部称为“队首”,尾部称为“队尾”,把元素加入队尾称为“入队”,删除队首元素称为“出队”。队列实现基于链表的实现将链表的头节点和尾结点分别视为“队首”和“队尾”,规定队尾仅可添加节点,队首仅可删除节点。......
  • 基于python学生兼职平台系统的设计与实现-附源码160938
    摘 要当今人类社会已经进入信息全球化和全球信息化、网络化的高速发展阶段。丰富的网络信息已经成为人们工作、生活、学习中不可缺少的一部分。人们正在逐步适应和习惯于网上贸易、网上购物、网上支付、网上服务和网上娱乐等活动,人类的许多社会活动正在向网络化发展。兼职......
  • 基于微信小程序的鲜花商城 毕业设计-附源码00942
    摘 要本论文研究了基于微信小程序的鲜花商城设计与实现,主要针对普通用户、管理员和商家用户三种角色设计了不同的功能和界面。对于普通用户,提供了首页展示、鲜花商城浏览、购物车管理、个人信息查看等功能;管理员则可以管理系统用户、轮播图、通知公告、商城商品等内容;商家......
  • 简单的linux系统学习笔记——09
    一、用户分类1.root//皇帝用户,定制规则用户,系统高级管理员【uid,gid0】2.普通用户//有特定的权限,权限是root授予的【uid,gid大于1000】3.傀儡用户//没有家目录,不能登录系统;【0-999】二、用户相关的配置文件1.用户列表文件[root@c7-100~]#cat/etc/passwdroot:x......
  • RabbitMQ消息队列:概念、单节点和集群示例
    目录消息队列概念主流的消息队列消息队列名词(1)Broker(2)Topic(3)Producer(4)Consumer(5)Queue(6)Message消息队列中两种工作模式Point-to-Point(PTP、点到点)Pub/Sub消息队列的缺点系统可用性降低系统复杂性提高数据一致性无法保证RabbitMQ相关术语(1)生产者(2)消费者(3)队......
  • 王苏安说钢材@309s不锈钢无缝管的工艺流程详细介绍
    309S不锈钢无缝管的工艺流程一共分为五步,分别是①切割、②弯曲、③成型、④焊接、⑤表面处理  ①切割:309s不锈钢无缝管的切割方法有剪切、火焰切割、机械切割、等离子切割等,其中薄型材料可以用剪切或切割机进行,厚型材料可以用火焰切割和等离子切割。  ②弯曲:冷弯能够让3......
  • 【数据结构】详细介绍栈和队列,解析栈和队列每一处细节
    目录一.栈1. 栈的概念2. 栈的实现2.1栈的结构2.2初始化栈2.3入栈2.4出栈2.5获取栈顶元素2.6获取栈中有效个数2.7判断栈是否为空2.8销毁栈 二.队列1.队列的概念2.队列的实现 2.1队列的结构2.2队列初始化 2.3销毁队列 2.4入队列(队尾) ......