首页 > 编程语言 >代码随想录算法训练营第九天|232.用栈实现队列、225.用队列实现栈、 20.有效的括号、1047.删除字符串中的所有相邻重复项

代码随想录算法训练营第九天|232.用栈实现队列、225.用队列实现栈、 20.有效的括号、1047.删除字符串中的所有相邻重复项

时间:2024-07-01 21:56:23浏览次数:21  
标签:第九天 obj 队列 随想录 return int MyStack stack

文章目录

232.用栈实现队列

题目链接:232. 用栈实现队列 - 力扣(LeetCode)
题目描述:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。

思路–直接模拟

设置两个栈,一个输入栈,一个输出栈,在push操作时,只需要将数据放进输入栈即可,但是在pop的时候,如果输出栈为空,就需要先把输入栈全部数据放进输出栈,再从输出栈弹出数据,如果输出栈为不为空,直接弹出数据即可。
当输入栈和输出栈均为空时,模拟队列为空

typedef struct {
    int input[100];
    int output[100];
    int inputTop;
    int outputTop;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue *obj=(MyQueue*)malloc(sizeof(MyQueue));
    obj->inputTop=0;
    obj->outputTop=0;
    return obj;
}
void myQueuePush(MyQueue* obj, int x) {
    obj->input[obj->inputTop]=x;
    obj->inputTop++;
}
int myQueuePop(MyQueue* obj) {
    if(obj->outputTop==0){//输出栈为空时,将输入栈全部数据放进输出栈中
        while(obj->inputTop){
            obj->inputTop--;
            obj->output[obj->outputTop++]=obj->input[obj->inputTop];
        }
    }
    int ans=obj->output[obj->outputTop-1];
    obj->outputTop--;
    return ans;
}
int myQueuePeek(MyQueue* obj) {
    if(obj->outputTop==0){
        return obj->input[0];
    }
    return obj->output[obj->outputTop-1];
}

bool myQueueEmpty(MyQueue* obj) {
    if(obj->inputTop==0&&obj->outputTop==0){
        return true;
    }
    return false;
}

void myQueueFree(MyQueue* obj) {
    free(obj);
    obj=NULL;
}

225.用队列实现栈

题目链接:225. 用队列实现栈 - 力扣(LeetCode)
题目描述:请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。

只能使用单端队列

解法一、两个队列模拟

设置两个队列queue1、queue2,先用queue2备份queue1,弹出最后面的元素,再把其他元素从queue2导回queue1,就做到了后进先出

typedef struct {
    int que1[100];
    int rear1,front1;
    int que2[100];//备份队列
    int rear2,front2;
} MyStack;
MyStack* myStackCreate() {
    MyStack *stack=(MyStack*)malloc(sizeof(MyStack));
    stack->front1=0,stack->front2=0;
    stack->rear1=0,stack->rear2=0;
    return stack;
}
void myStackPush(MyStack* obj, int x) {
    obj->que1[obj->rear1++]=x;
}
int myStackPop(MyStack* obj) {
    // //优化:复制队列头尾指针,减少对内存的访问次数
    int rear1=obj->rear1;
    int rear2=obj->rear2;
    int front1=obj->front1;
    int front2=obj->front2;
    while(front1<rear1){//将que1备份到que2中
        obj->que2[rear2++]=obj->que1[front1++];
    }
    rear1=0,front1=0;
    int top=obj->que2[--rear2];//弹出最后一个元素
    while(front2<rear2){//将que2导回que1
        obj->que1[rear1++]=obj->que2[front2++];
    }
    obj->rear1=rear1,obj->front1=front1;
    obj->rear2=0,obj->front2=0;
    return  top;
}
int myStackTop(MyStack* obj) {
    return obj->que1[obj->rear1-1];
}
bool myStackEmpty(MyStack* obj) {
    return obj->front1==obj->rear1 ? true:false;
}
void myStackFree(MyStack* obj) {
    free(obj);
    obj=NULL;
}

解法二、一个队列模拟

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

typedef struct {
    int que[100];
    int rear,front;
} MyStack;
MyStack* myStackCreate() {
    MyStack *stack=(MyStack*)malloc(sizeof(MyStack));
    stack->rear=0;
    stack->front=0;
    return stack;
}
void myStackPush(MyStack* obj, int x) {
    obj->que[obj->rear++]=x;
}
int myStackPop(MyStack* obj) {
    int rear=obj->rear;
    int front=obj->front;
    int temp=rear;
    while(front<temp-1){
        obj->que[rear++]=obj->que[front++];
    }
    int top=obj->que[front++];
    obj->rear=rear;
    obj->front=front;
    return top;
}
int myStackTop(MyStack* obj) {
    return obj->que[obj->rear-1];
}
bool myStackEmpty(MyStack* obj) {
    return obj->rear==obj->front?true:false;
}
void myStackFree(MyStack* obj) {
    free(obj);
    obj=NULL;
}

20.有效的括号

题目链接:20. 有效的括号 - 力扣(LeetCode)
题目描述:给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

栈模拟

bool isValid(char * s){
   int len=strlen(s);
   char *stack=(char*)malloc(sizeof(char)*len);
   int top=0;
   for(int i=0;i<len;i++){
       if(s[i]=='('||s[i]=='['||s[i]=='{'){
           stack[top++]=s[i];
       }
       else{
          if((--top)<0)  return false;
          if(s[i]==')'&&stack[top]!='(')  return false;
          if(s[i]==']'&&stack[top]!='[')  return false;
          if(s[i]=='}'&&stack[top]!='{')  return false;
       }
   }
   return (!top); //防止出现【情况
}

1047.删除字符串中的所有相邻重复项

题目链接:1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)

题目描述:给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

提示:

  1. 1 <= S.length <= 20000
  2. S 仅由小写英文字母组成。

解法一、栈

char * removeDuplicates(char * s){
    //求出字符串长度
    int strLength = strlen(s);
    //开辟栈空间。栈空间长度应为字符串长度+1(为了存放字符串结束标志'\0')
    char* stack = (char*)malloc(sizeof(char) * strLength + 1);
    int stackTop = 0;

    int index = 0;
    //遍历整个字符串
    while(index < strLength) {
        //取出当前index对应字母,之后index+1
        char letter = s[index++];
        //若栈中有元素,且栈顶字母等于当前字母(两字母相邻)。将栈顶元素弹出
        if(stackTop > 0 && letter == stack[stackTop - 1])
            stackTop--;
        //否则将字母入栈
        else
            stack[stackTop++] = letter;
    }
    //存放字符串结束标志'\0'
    stack[stackTop] = '\0';
    //返回栈本身作为字符串
    return stack;
}

解法二、双指针

char * removeDuplicates(char * s){
    //创建快慢指针
    int fast = 0;
    int slow = 0;
    //求出字符串长度
    int strLength = strlen(s);
    //遍历字符串
    while(fast < strLength) {
        //将当前slow指向字符改为fast指向字符。fast指针+1
        char letter = s[slow] = s[fast++];
        //若慢指针大于0,且慢指针指向元素等于字符串中前一位元素,删除慢指针指向当前元素
        if(slow > 0 && letter == s[slow - 1])
            slow--;
        else
            slow++;
    }
    //在字符串结束加入字符串结束标志'\0'
    s[slow] = 0;
    return s;
}

标签:第九天,obj,队列,随想录,return,int,MyStack,stack
From: https://blog.csdn.net/semirc9/article/details/140111088

相关文章

  • 代码随想录算法训练营Day9 | 字符串 151.翻转字符串单词 28.实现strStr() KMP算法介绍
    python中常用:        s[::-1]: 反转整个字符        s.strip():删除开头或结尾处的空白字符     s.split():字符拆分成单词 →list    “”.join(s):list→字符串   (持续更新…) 151.翻转字符串里的单词 题目: Leetcod......
  • Day61 代码随想录打卡|回溯算法篇---组合优化
    本篇是针对上一题的优化,因为在计算所有可能的组合结果时,不是每一条路径都是我们需要遍历的,如图,当n和k都为4的时候,其实最终的结果只有一个[1,2,3,4]是符合结果的。因此我们遍历的时候就不需要遍历每一条边,而是只需要沿着1,2,3,4的路径直接下来即可。那么我们怎么控制循环变量使得......
  • 代码随想录算法训练营第四十三天 | 52.携带研究材料 518.零钱总和II 377.组合总和IV 7
    完全背包有N件物品和一个最多能被重量为W的背包,第i间物品的重量为weights[i],价值为value[i],每件物品都有无限个,求解将哪些物品装入背包里,物品价值总和最大遍历顺序:纯完全背包问题(即求装满背包后的最大价值)先遍历背包先遍历物品都是可以的和零一背包求解的最大不同就是遍历顺序......
  • 消息队列面试题----基础篇
    ##1、为什么要用MQ?MQ有哪些使用场景?###什么是消息队列消息队列是一种异步的通信方式,用于在分布式系统中管理消息传递。消息队列采用了生产者-消费者模型,生产者将消息发送到队列中,而消费者则从队列中接收消息。###为什么要使用消息队列其实就是问问你消息队列都有哪些使......
  • RabbitMQ延时任务通过死信队列实现(golang)
    最近在一个项目中,需要实现在用户上传图片30分钟后,删除对应图片,以保证用户隐私。我们使用rabbitmq来实现。基于rabbitmq实现延时任务有两种方式,一种为队列ttl+死信exchange,另一种为安装插件(https://github.com/rabbitmq/rabbitmq-delayed-message-exchange)。其中安装......
  • 代码随想录算法训练营第四十二天 | 1049最后一块石头的重量II 494.目标和 474.一和零
    1049.最后一块石头的重量题目链接文章讲解视频讲解解题思路:  将石头尽量分为相等的两堆,两堆最差即为所求结果  石头的重量就是石头的价值动规五部曲:dp[j]:表示背包容量为j时可以装的石头的总价值递推公式:dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]初始化:均......
  • 探索数据结构:队列的的实现与应用
     ......
  • 代码随想录算法训练营第十天|232.用栈实现队列、225.用队列实现栈、20.有效的括号、 1
    今天学习了栈与队列这两个数据结构,栈是一个先进后出的结构,在C++中用stack进行表示,有push、pop、top、empty这些属性;队列是一个先进后出的结构,有push、pop、front、back。empty这些属性。在底层实现上,他们都是用deque双向队列进行实现的。232.用栈实现队列题目链接:232.用栈......
  • 代码随想录算法训练营第九天|151.翻转字符串里的单词,卡码网:55.右旋转字符串
    151.翻转字符串里的单词题目链接:151.反转字符串中的单词-力扣(LeetCode)题目要求是给定一个字符串,要求把里面的单词进行倒序输出,并且要删除里面多余的空格。我的第一种做法是把里面的字符串提取出来,然后倒序放入一个新的字符串中,这样空间复杂度会比较高,也AC了,但肯定不是最......
  • 消息队列选型之 Kafka vs RabbitMQ
    在面对众多的消息队列时,我们往往会陷入选择的困境:“消息队列那么多,该怎么选啊?Kafka和RabbitMQ比较好用,用哪个更好呢?”想必大家也曾有过类似的疑问。对此本文将在接下来的内容中以Kafka和RabbitMQ为例分享消息队列选型的一些经验。一、什么是消息队列消息队列即Messag......