首页 > 其他分享 >【LeetCode剑指offer 01】数组中重复的数字、两个栈实现队列

【LeetCode剑指offer 01】数组中重复的数字、两个栈实现队列

时间:2023-04-05 23:00:18浏览次数:58  
标签:deleteHead 01 offer 队列 res LeetCode int stack out

数组中重复的数字

数组中重复的数字

找出数组中重复的数字。

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

限制:

2 <= n <= 100000

思路

很容易想到使用哈希表来记录元素出现次数

且因为题目规定了n的范围,所以我们使用的哈希表类型应该是map

代码

第一版

直接定义一个unordered_map

然后遍历数组,在哈希表对应位置计数,最后再遍历哈希表,返回第一个遇到的出现次数大于等于2的元素

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        //定义一个map
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); ++i){
            hash[nums[i]]++;
        }
        //在哈希表中找出现次数大于等于2的元素
        for(unordered_map<int, int>::iterator it = hash.begin(); it != hash.end(); ++it){
            if(it->second >= 2) return it->first;
        }
        return -1;
    }
};

这么做其实有点冗余,其实完全可以只用一个循环解决问题的

意思就是,我们其实可以不用记录元素出现的具体次数,只要在遍历时又碰到了即可直接返回

于是有了第二版

第二版
class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        //定义一个map
        unordered_map<int, int> hash;
        //遍历数组,将元素加入哈希表,同时判断某元素是否重复出现
        for(int num : nums){
            if(hash[num]) return num;//当前遍历值出现在哈希表,为重复值,返回
            hash[num]++;//未出现的,则在哈希表中记录
        }
        return -1;
    }
};

用两个栈实现队列

用两个栈实现队列

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

示例 1:

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

示例 2:

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

提示:

1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用

思路

一拿到题肯定会下意识联想到 232. 用栈实现队列

这题之前刷代码随想录的时候写过,于是很自然的照着以前的思路写

事实上,这两题的核心思路是一样的,即使用两个栈(stack_in和stack_out),分别模拟队列的进和出

模拟加入队列功能的栈stack_in就直接使用push功能就行;

模拟从队列拿数据时,要先判断 stack_out 是否为空,不为空可以直接取该数据作为当前队列的头部数据

如果为空,就把 stack_in 的所有数据弹出,然后压入 stack_out ,然后取 stack_out 栈顶数据作为当前队列的头部数据,最后弹出栈顶数据

代码与坑

如果真是这么顺利就ac了我也不会特地写个记录

最开始我是完全按照之前的思路去写的代码,如下:

class CQueue {
public:
    //定义两个栈
    stack<int>stack_in;
    stack<int>stack_out;

    CQueue() {

    }
    
    void appendTail(int value) {
        stack_in.push(value);
    }
    
    int deleteHead() {
        if (stack_in.empty()) return -1;
        if(!stack_out.empty()) {
            return stack_out.top();
        }else{
            while(!stack_in.empty()){
                stack_out.push(stack_in.top());//问题位置
                stack_in.pop();
            }
            int res = stack_out.top();
            return res;
        }        
    }
};

看起来很好,但是第一个用例都过不去

后面经过定位发现问题出现在交换两个栈元素的过程中

如果像上面那样写,可能出现莫名其妙的错误(原因TBD)

所以后面我用一个变量来接收弹出数据,然后再入栈(老老实实的写)

至少不会错了,以下是ac代码

class CQueue {
public:
    //定义两个栈
    stack<int>stack_in;
    stack<int>stack_out;

    CQueue() {

    }
    
    void appendTail(int value) {
        stack_in.push(value);
    }
    
    int deleteHead() {
        int res;//用于保存弹出栈的数据
        if(!stack_out.empty()){//当stack_out不为空,先将该数获取为res,然后弹出
            res = stack_out.top();
            stack_out.pop();
            return res;
        }else if(!stack_in.empty()){//当stack_in不为空,循环将所有数加入stack_out中
            while(!stack_in.empty()){
                res = stack_in.top();
                stack_in.pop();
                stack_out.push(res);
                // stack_out.push(stack_in.top());//这种写法会出错
                // stack_in.pop();      
            }
            // res = stack_out.top();
            stack_out.pop();//两个栈交换完数据后,直接将stack_out的栈顶弹出
            return res;//当前res记录的是最后一个压入stack_out的数据,即stack_out的栈顶数据,返回即可
        }else{//栈为空时,返回-1
            return -1;
        } 
    }
};

以下写法在 232. 用栈实现队列仍使用

stack_out.push(stack_in.top());//这种写法会出错
stack_in.pop(); 

为了保证统一,均修改为本题中的这种写法

为什么会出错?

代码1
int res;
res = stack_in.top();
stack_in.pop();
stack_out.push(res);

代码2
stack_out.push(stack_in.top());
stack_in.pop();  

这两种写法有何区别?为什么代码2在某些情况下会出错?

这两种写法的功能是相同的,都是将 stack_in 的栈顶元素弹出并压入 stack_out 中。但是,它们之间存在一些细微的区别。

主要是顺序不同

代码1先将栈顶元素存储到 res 中,再将 res 压入 stack_out 栈中,而代码2直接将 stack_in 栈顶元素压入 stack_out 栈中。

如果 stack_in 为空栈,那么代码1和代码2都会出错,因为都会试图访问空栈的栈顶元素。

但是,如果 stack_out 栈非空,那么代码2在将 stack_in 栈顶元素压入 stack_out 栈之前,没有先检查 stack_out 栈是否为空,因此可能会导致将元素插入到错误的位置

因此,如果 stack_out 栈非空,最好使用代码1的写法。事实上,如果没超时,都无脑用第一种方式就行。

标签:deleteHead,01,offer,队列,res,LeetCode,int,stack,out
From: https://www.cnblogs.com/DAYceng/p/17291239.html

相关文章

  • VS2012、VS2013、VS2015、VS2019 代码自动注释插件【2】
    Git代码自动注释工具源码地址 VS2010、VS2012、VS2013的代码自动注释插件。安装该插件后,可以在VS的菜单中显示“注释”主菜单,可以给类、函数、成员添加标准的注释,与Doxygen配合使用,可以直接生成项目的注释文档。【插件下载】高版本的VS,可以下载源码后,自行编译使用。【插件安装】......
  • IntelliJ IDEA 2019 快捷键
    打开关闭左侧文件夹:Alt+1运行程序:Shift+F10编译程序:Ctrl+Shift+F10代码提示:Ctrl+Space格式化代码:Ctrl+Alt+L在方法间跳转:Ctrl+Alt+向上/向下箭头在文件间跳转:Ctrl+Tab查找文件:Ctrl+Shift+N查找类、方法:Ctrl+N查找文本:Ctrl+F替换文本:Ctrl......
  • [oeasy]python0127_中文系统_gbk_BIG5_南极星_内码转化
    中文系统bgk回忆上次内容汉字字形通过点阵式打字机像素级寻址的屏幕进入了计算机的世界在海峡对岸的台湾同胞也进入了汉字时代他们会使用GB2312编码吗?能互通吗?......
  • [oeasy]python0127_中文系统_gbk_BIG5_南极星_内码转化
    中文系统bgk回忆上次内容汉字字形通过点阵式打字机像素级寻址的屏幕进入了计算机的世界 ​ 添加图片注释,不超过140字(可选) 在海峡对岸的台湾同胞也进入了汉字时代 他们会使用GB2312编码吗?能互通吗?......
  • stm32-----01初识GPIO
    GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct)  -----使用结构体的参数来初始化GPIO口,一般初始化外设都用这个函数完成先定义一个结构体变量给结构体赋值调用这个函数  GPIO的4个写入函数GPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGP......
  • ACCT3013 Financial 描述分析
    ACCT3013ACCT3013FinancialStatementAnalysisMid-semesterTake-HomeAssessmentSemesterOne,2023GeneralinformationDuedateandtime:Wednesday,11am,5thApril(SydneyTime)1.Youarenotpermittedtouseanyartificialintelligence(AI)tools,suchasC......
  • Leetcode(剑指offer专项训练)——DP专项(7)
    矩阵中的距离题目:给定一个由0和1组成的矩阵mat ,请输出一个大小相同的矩阵,其中每一个格子是mat中对应位置元素到最近的0的距离。两个相邻元素间的距离为1。链接TLS思路题解暴力DFS的结果是超时......
  • 如何选择 Offer?
    阅读文本大概需要2.6分钟。前两天,有一位读者在我文章下面留言,为了保护隐私,昵称和头像都打码了:我给他回复了我的建议,但是我觉得这个问题很有代表性,我准备在这里重新说下我的观点,以及详细阐述我的理由与分析。我给他的建议是选择上海的Offer。从这位同学的描述中,可以感觉到,虽然他......
  • 01]TMS FlexCel VCL & FMX v7.8的下载和安装
    00]TMS FlexCel VCL & FMX v7.8的下载链接:https://pan.baidu.com/s/12RhG-d6nsX5EZx0bVtIrFw提取码:mhq201]TMSFlexCelVCL&FMXv7.8的安装DELPHI10.3安装TMSFlexCelVCL&FMXv7.8方法:1、文件解压到:D:\TMSFlexCelVCL&FMXv7.82、添加路径:D:\TMSFlexCelVCL......
  • 01:python基础
      正文#打印内容print()输入内容input()print("helloWorld!")#1:注释:输入内容#name=input("请输入你的名字:")#print("hello,",name,"您好")print("1024*768=",1024*768)#2:4个缩进代表代码块#Python程序是大小写敏感的,如果写错了大小写,程序会......