代码随想录 Day8 栈(FILO)与队列(FIFO) LeetCode T232 用栈实现队列 LeetCodeT225 用队列实现栈

news2024/11/26 18:52:52

 题目详细思路来自于:代码随想录 (programmercarl.com)

栈和队列都是大家不陌生的数据结构,我们之前的栈和队列一般是用数组或链表来实现的 ,

这里我们给出实现方式,用于帮助更好的理解.

1.用链表实现栈 

/* 基于链表实现的栈 */
class LinkedListStack {
private ListNode stackPeek; // 将头节点作为栈顶
    private int stkSize = 0; // 栈的长度
public LinkedListStack() {
    stackPeek = null;
}
/* 获取栈的长度 */
public int size() {
    return stkSize;
}
/* 判断栈是否为空 */
public boolean isEmpty() {
    return size() == 0;
}
/* 入栈 */
public void push(int num) {
    ListNode node = new ListNode(num);
    node.next = stackPeek;
    stackPeek = node;
    stkSize++;
}
/* 出栈 */
public int pop() {
    int num = peek();
    stackPeek = stackPeek.next;
    stkSize--;
    return num;
}
/* 访问栈顶元素 */
public int peek() {
    if (size() == 0)
        throw new IndexOutOfBoundsException();
    return stackPeek.val;
}
/* 将 List 转化为 Array 并返回 */
public int[] toArray() {
    ListNode node = stackPeek;
    int[] res = new int[size()];
    for (int i = res.length - 1; i >= 0; i--) {
        res[i] = node.val;
        node = node.next;
        }
    return res;
    }
}

 2.用数组实现栈

class ArrayStack {
    private ArrayList<Integer> stack;
    public ArrayStack() {
// 初始化列表(动态数组)
        stack = new ArrayList<>();
}
/* 获取栈的长度 */
public int size() {
    return stack.size();
}
/* 判断栈是否为空 */
public boolean isEmpty() {
    return size() == 0;
}
/* 入栈 */
public void push(int num) {
    stack.add(num);
}
/* 出栈 */
public int pop() {
    if (isEmpty())
        throw new IndexOutOfBoundsException();
    return stack.remove(size() - 1);
}
/* 访问栈顶元素 */
public int peek() {
    if (isEmpty())
        throw new IndexOutOfBoundsException();
    return stack.get(size() - 1);
}
/* 将 List 转化为 Array 并返回 */
public Object[] toArray() {
    return stack.toArray();
    }
}

 3.两种实现的优缺点

3.1 用数组实现栈的优缺点

在基于数组的实现中,入栈和出栈操作都是在预先分配好的连续内存中进行,具有很好的缓存本地性,因此效率较高。然而,如果入栈时超出数组容量,会触发扩容机制,导致该次入栈操作的时间复杂度变为 𝑂(𝑛).

 

3.2 用链表实现栈的优缺点

在链表实现中,链表的扩容非常灵活,不存在上述数组扩容时效率降低的问题。但是,入栈操作需要初始化节点对象并修改指针,因此效率相对较低。不过,如果入栈元素本身就是节点对象,那么可以省去初始化步骤,从而提高效率。

4. 用链表实现队列

class LinkedListQueue {
    private ListNode front, rear; // 头节点 front ,尾节点 rear
    private int queSize = 0;
public LinkedListQueue() {
    front = null;
    rear = null;
}
/* 获取队列的长度 */
public int size() {
    return queSize;
}
/* 判断队列是否为空 */
public boolean isEmpty() {
    return size() == 0;
}
/* 入队 */
public void push(int num) {
// 尾节点后添加 num
    ListNode node = new ListNode(num);
// 如果队列为空,则令头、尾节点都指向该节点
    if (front == null) {
        front = node;
        rear = node;
// 如果队列不为空,则将该节点添加到尾节点后
        } else {
        rear.next = node;
        rear = node;
        }
    queSize++;
}
/* 出队 */
public int pop() {
    int num = peek();
// 删除头节点
    front = front.next;
    queSize--;
    return num;
}
/* 访问队首元素 */
public int peek() {
    if (size() == 0)
        throw new IndexOutOfBoundsException();
    return front.val;
}
/* 将链表转化为 Array 并返回 */
public int[] toArray() {
    ListNode node = front;
    int[] res = new int[size()];
    for (int i = 0; i < res.length; i++) {
        res[i] = node.val;
        node = node.next;
        }
    return res;
    }
}

5.用数组实现队列

你可能会发现一个问题:在不断进行入队和出队的过程中, front 和 rear 都在向右移动, 当它们到达数组尾部时就无法继续移动了。为解决此问题,我们可以将数组视为首尾相接的“环形数组”。对于环形数组,我们需要让 front 或 rear 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现

/* 基于环形数组实现的队列 */
class ArrayQueue {
    private int[] nums; // 用于存储队列元素的数组
    private int front; // 队首指针,指向队首元素
    private int queSize; // 队列长度
public ArrayQueue(int capacity) {
    nums = new int[capacity];
    front = queSize = 0;
}
/* 获取队列的容量 */
public int capacity() {
    return nums.length;
}
/* 获取队列的长度 */
public int size() {
    return queSize;
}
/* 判断队列是否为空 */
public boolean isEmpty() {
    return queSize == 0;
}
/* 入队 */
public void push(int num) {
    if (queSize == capacity()) {
        System.out.println(" 队列已满");
        return;
}
// 计算尾指针,指向队尾索引 + 1
// 通过取余操作,实现 rear 越过数组尾部后回到头部
    int rear = (front + queSize) % capacity();
// 将 num 添加至队尾
    nums[rear] = num;
    queSize++;
}
/* 出队 */
public int pop() {
    int num = peek();
// 队首指针向后移动一位,若越过尾部则返回到数组头部
    front = (front + 1) % capacity();
    queSize--;
    return num;
}
/* 访问队首元素 */
public int peek() {
    if (isEmpty())
        throw new IndexOutOfBoundsException();
        return nums[front];
}
/* 返回数组 */
public int[] toArray() {
// 仅转换有效长度范围内的列表元素
    int[] res = new int[queSize];
    for (int i = 0, j = front; i < queSize; i++, j++) {
        res[i] = nums[j % capacity()];
        }
        return res;
    }
}

LeetCode T232 用栈实现队列

题目链接:

232. 用栈实现队列 - 力扣(LeetCode) 

题目思路:

我们这里就要用两个栈来实现队列,一个是stackOut,一个是stackIn,in栈负责将要入队的添加进来,但是这时候我们发现出栈的话会和队列的出队顺序相反,所以我们再入栈一次,这样出栈的顺序就颠倒过来啦,也完美的实现队列的基本功能.

注:一定要将In栈的全部元素一起push进Out栈,否则顺序可能会发生变化,这样就影响了正常的出栈功能.

题目代码:

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();

    }
    
    public void push(int x) {
        stackIn.push(x);

    }
    
    public int pop() {
        downStackIn();
        return stackOut.pop();
       

    }
    
    public int peek() {
        downStackIn();
        return stackOut.peek();

    }
    
    public boolean empty() {
        downStackIn();
        return stackOut.isEmpty();

    }
    public void downStackIn()
    {
        while(!stackOut.isEmpty())
        {
            return;
        }
        while(!stackIn.isEmpty())
        {
            stackOut.push(stackIn.pop());
        }
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

LeetCode T225 用队列实现栈

题目链接:225. 用队列实现栈 - 力扣(LeetCode)

题目思路:

这里我们同样可以用和上一题同样的思路实现,但是为了更有挑战性,我们决定用一个队列来实现栈,假设我们入队元素是123,此时我们需要的出队元素应该是3,那么我们该如何操作呢,其实,我们只需要让前两个元素重新入队,这样第一个出队的元素就是3了,其实就是前size()-1个元素重新入队,就实现了出栈的操作

这里我使用的是deque,这个类可以实现两天的操作,就是比queue多了两头操作的一些方法.

题目代码:

class MyStack {
    Deque<Integer> que1;

    public MyStack() {
        que1 = new ArrayDeque<>();

    }
    
    public void push(int x) {
        que1.addLast(x);

    }
    
    public int pop() {
        int tmp = que1.size()-1;
        while(tmp>0)
        {
            que1.addLast(que1.peekFirst());
            que1.pollFirst();
            tmp--;
        }
        return que1.pollFirst();

    }
    
    public int top() {
        return que1.peekLast();

    }
    
    public boolean empty() {
        return que1.isEmpty();

    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */

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

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

相关文章

记录我的网站的上线的全过程

我的网站开发全过程记录: 提示: 大部分是cv代码,少部分样式进行了修改和借鉴,主要花费时间在部署上面,出现的问题 开始: 三个博主: 在掘金上认识了搜狐前端-- 英杰 , 掘金链接:yingjieweb 的个人主页 - 动态 - 掘金 偶然间看见了英杰的网站,感觉非常不错,产生自己弄的想法,…

mybatis-spring集成数据库连接池开启注解式开发

目录 1. 引入依赖包 2. 集成配置文件 2.1 开启注解式开发 2.2 spring引入外部配置文件 2.3 数据库连接池 2.4 spring整合mybatis 2.5 自动代理 3. 注解式开发的几个常用注解 4. spring-test 附录一&#xff1a;spring常用注解 1. 引入依赖包 <!--spring整合mybat…

【面试经典150 | 矩阵】旋转图像

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;原地旋转方法二&#xff1a;翻转代替旋转 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带…

Mac安装Ecplise产品报错:dose not contain the JNI_CreateJavaVM symbol

1. 絮絮叨叨 工作中需要借助Ecplise Memory Analyzer (MAT)分析dump文件&#xff0c;直接下载、安装、运行MAT报错 询问同事后&#xff0c;同事说可以先安装Ecplise&#xff0c;再以插件的形式安装MAT下载、安装好Eclipse&#xff0c;点击运行仍然报错&#xff0c;且错误信息一…

区块链3.0时代 基于GoMars构建的新概念TravelFi能否注入新力量?

区块链技术进入3.0时代 后疫情时代&#xff0c;全球数字化进程不断加快&#xff0c;世界范围内的移动通信、互联网技术及各类数字化应用的社会普及率也正在快速提升&#xff0c;疫情推动了互联网经济的增长&#xff0c;也让数字经济的价值开始显现。 数字经济一词的由来至今已经…

2023最新注册小程序以及云开发环境的创建

前言&#xff1a; 我们前面虽然可以用测试号创建小程序,但是测试号有很多功能会受限,比如我们接下来要讲的云开发,必须是注册小程序后才可以使用, 一&#xff0c;注册小程序 官方注册文档&#xff1a; 产品定位及功能介绍 | 微信开放文档 (qq.com)https://developers.weixin.…

servlet 线程模型 异步

在 servlet 3.0 之前&#xff0c;请求与线程的对应关系是1:1&#xff0c;对应jvm与操作系统的线程的关系。 https://jcp.org/en/jsr/detail?id315 https://jcp.org/en/jsr/detail?id340 从 servlet 3.0 开始&#xff0c;开始有了异步相关功能 容器线程池与业务线程池开始单独…

第九章 动态规划 part13 300. 最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

第五十二天| 第九章 动态规划 part13 300. 最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组 一、300. 最长递增子序列 题目链接&#xff1a;https://leetcode.cn/problems/longest-increasing-subsequence/ 题目介绍&#xff1a; 给你一个整数数组 nums &#xff…

xilinx的原语的使用

xilinx的原语的使用 在学习FPGA实现千兆网时需要GMII转RGMII&#xff0c;这就涉及了原语的使用&#xff0c;特此记录&#xff01; 一、原语 与RGMII接口相关的原语&#xff1a; BUFG:全局时钟网络 BUFIO&#xff1a;只能采集IO的数据&#xff0c;采集IO数据的时候延时是最低的…

力扣-169. 多数元素(C语言+分治递归)

1. 题目 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 2. 输入输出样例 示例1 输入&#xff1a;nums [3,2,3] 输出&#xff…

指定vscode黏贴图片路径(VSCode 1.79 更新)

指定vscode黏贴图片路径(VSCode 1.79 更新) 设置中搜索"markdown.copyFiles.destination" 点击AddItem,配置你的key-value&#xff0c;完成。

VUE2项目:尚品汇-axios二次封装请求以及VUEX的状态管理库

上一篇&#xff1a;VUE2项目&#xff1a;尚品汇VUE-CLI脚手架初始化项目以及路由组件分析&#xff08;一&#xff09; 目录 axios二次封装API接口管理与解决跨域API接口管理nprogress进度条配置 VUEX状态管理库三级分类动态背景颜色防抖三级联动跳转路由分析 axios二次封装 项…

12链表-双指针

目录 LeetCode之路——21. 合并两个有序链表 分析&#xff1a; LeetCode之路——19. 删除链表的倒数第 N 个结点 分析&#xff1a; LeetCode之路——21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的…

网络运营和电子商务有什么区别

大家好&#xff0c;我是网络工程师成长日记实验室的郑老师&#xff0c;您现在正在查看的是网络工程师成长日记专栏&#xff0c;记录网络工程师日常生活的点点滴滴 一个同学他问我&#xff0c;他说学网络运营的话&#xff0c;它是不是电子商务里面的这个东西&#xff1f;像电子大…

二十六、设置时序电路初始状态的方法(初始值设置)(时序电路置数)2

方法2 在理解方法1的化简(1)这个方法后,又可以想到输入触发器R和S两个输入端的信号也无非就是0和1。那么直接用LOAD这个信号接在R和S两个输入端上即可。 先用开关判断触发器的R和S是低电平触发还是高电平触发(下图触发器可以直接看出为低电平触发,但是实际用管子搭建的触…

【那些年写过的愚蠢代码】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

一维数组和二维数组的使用(char类型)

目录 导读1. 字符数组1.1 字符数组的创建1.2 字符数组的初始化1.3 不同初始化在内存中的不同1.3.1 strlen测试1.3.2 sizeof测试1.3.3 差异原因 1.4 字符数组的使用 2. 数组越界3. 数组作为函数参数博主有话说 导读 我们在前面讲到了 int 类型的数组的创建和使用&#xff1a; 一…

【【萌新的Risc-V学习之再看读不懂的流水线设计-10】】

萌新的Risc-V学习之再看读不懂的流水线设计-10 我们将流水线和之前案例中洗衣服的例子进行对照 我们把整个流水线分为5个阶段 也就是做成五级流水线 IF: 取指令ID: 指令译码和读寄存器堆EX: 执行或计算地址MEM: 数据存储器访问WB: 写回 我先在这里表述一下基本的几个指令的用…

javaSwing销售管理

​ 目录 一、选题背景 近几年来&#xff0c;传统商业与电商似乎是水火不容&#xff0c;大有不是你死便是我活的劲头。一直以来舆论都是一边倒的电商将迅速取代传统零售的论调&#xff0c;然而几年过去&#xff0c;电商的发展确实值得侧目&#xff0c;但传统商业虽然受到不小的…

深入学习git

1、git原理及整体架构图 一些常用的命令 git add . 或 git add src/com/ygl/hello/hello.java 指定文件 git commit . 或 git commit src/com/ygl/hello/hello.java 指定文件 git push origin 分支名称 2、git stash的应用场景 场景一&#xff1a;你正在当前分支A开发&…