代码随想录算法训练营第十一天| 20. 有效的括号 、1047. 删除字符串中的所有相邻重复项 、 150. 逆波兰表达式求值

 20. 有效的括号

题目链接/文章讲解/视频讲解:代码随想录

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

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

分析及思路

首先分析什么叫匹配,什么叫不匹配。当我们碰到'(','[','{'时我们直接入栈,当碰到')',']','}'时弹出栈,看出栈的数据是否和该括号匹配。

期间有一个不匹配则直接返回不匹配。

 代码及注释

// 定义元素类型为int
#define ElemType int
// 定义栈节点结构体
typedef struct StackNode{
    ElemType data; // 数据
    struct StackNode* next; // 指向下一个节点的指针
}StackNode,*LinkStack; // 定义栈节点类型和指向栈节点的指针类型

// 初始化栈
LinkStack initialize(void){
    LinkStack temp = (StackNode*)malloc(sizeof(StackNode)); // 为栈节点分配内存
    temp->next = NULL; // 将栈节点的指针域置空
    return temp; // 返回初始化后的栈
}

// 入栈操作
void StackPush(LinkStack Stack,ElemType data){
    StackNode* temp = (StackNode*)malloc(sizeof(StackNode)); // 为新节点分配内存
    temp->data = data; // 将数据存入新节点
    temp->next = Stack->next; // 将新节点插入到栈顶
    Stack->next = temp;
}

// 出栈操作
ElemType StackPop(LinkStack Stack){
    if(StackEmpty(Stack)){ // 如果栈为空
        return -1; // 返回-1表示出栈失败
    }
    StackNode* temp = Stack->next; // 指向栈顶节点
    Stack->next = temp->next; // 栈顶指针指向下一个节点
    int temp_data = temp->data; // 保存栈顶数据
    free(temp); // 释放栈顶节点内存
    return temp_data; // 返回栈顶数据
}

// 判断栈是否为空
bool StackEmpty(LinkStack Stack){
    return Stack->next == NULL; // 如果栈顶指针为空,表示栈为空
}

// 判断括号序列是否有效
int isValid(char* s) {
    LinkStack Stack = initialize(); // 初始化栈
    int s_len = strlen(s); // 获取字符串长度
    ElemType data1; // 用于保存出栈的数据
    for(int i=0;i<s_len;i++){ // 遍历输入的字符串
        switch(s[i]){ // 判断字符类型
            case '(':case '[':case '{': // 如果是左括号
                StackPush(Stack,s[i]); // 入栈
                break;
            case ')': // 如果是右圆括号
                data1 = StackPop(Stack); // 出栈
                if( data1 != '(' ) // 判断出栈的括号类型是否匹配
                    return 0; // 不匹配,返回0
                break;
            case ']': // 如果是右方括号
                data1 = StackPop(Stack); // 出栈
                if( data1 != '[' ) // 判断出栈的括号类型是否匹配
                    return 0; // 不匹配,返回0
                break;
            default: // 如果是右花括号
                data1 = StackPop(Stack); // 出栈
                if( data1 != '{' ) // 判断出栈的括号类型是否匹配
                    return 0; // 不匹配,返回0
        }
    }
    if(StackEmpty(Stack)) // 判断最终栈是否为空
        return 1; // 如果为空,返回1表示括号序列有效
    return 0; // 如果不为空,返回0表示括号序列无效
}

卡哥思路实现

int isValid(char* s) { // 定义一个函数isValid,参数为字符串s
    LinkStack Stack = initialize(); // 初始化一个链栈Stack
    int s_len = strlen(s); // 获取字符串s的长度
    ElemType data1; // 定义一个元素类型data1
    for(int i=0;i<s_len;i++){ // 循环遍历字符串s
        switch(s[i]){ // 判断当前字符
            case '(':StackPush(Stack,')');break; // 如果是'(',将')'压入栈中
            case '[':StackPush(Stack,']');break; // 如果是'[',将']'压入栈中
            case '{':StackPush(Stack,'}');break; // 如果是'{',将'}'压入栈中
            default:if( (StackEmpty(Stack)) || (StackPop(Stack)!=s[i]) )return 0; // 如果是其他字符,且栈为空或弹出的元素与当前字符不匹配,则返回0
        }
    }
    if(StackEmpty(Stack)) // 如果栈为空
        return 1; // 返回1
    return 0; // 否则返回0
}

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

题目链接/文章讲解/视频讲解:代码随想录

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

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

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

 分析及思路

分析相邻的就消掉,也就是最后一个访问的时候,看上一个字母是不是和它一样,推出最近最新访问的就是我们要寻找的元素,符合栈的特点,我们用栈来解决问题。

 代码及注释

// 定义一个函数,输入参数为字符指针,返回类型为字符指针
char* removeDuplicates(char* s) {
    // 获取输入字符串的长度
    int s_len = strlen(s);
    // 创建一个字符数组作为栈,长度为输入字符串长度加1
    char* stack = (char*)malloc(sizeof(char)*s_len+1);
    // 初始化栈顶指针为-1
    int StackTop = -1;
    // 遍历输入字符串
    for(int i=0;i<s_len;i++){
        // 如果栈为空或者栈顶字符与当前字符不相等,则将当前字符入栈
        if( (StackTop == -1) || (stack[StackTop] != s[i]) )
            stack[++StackTop] = s[i];
        // 如果栈顶字符与当前字符相等,则将栈顶字符出栈
        else
            StackTop--;
    }
    // 在栈顶指针位置添加字符串结束符
    stack[++StackTop] = '\0';
    // 返回去重后的字符串
    return stack;
}

 150. 逆波兰表达式求值 

题目链接/文章讲解/视频讲解:代码随想录

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

分析及思路

 就是后缀表达式,遇到数字就压入栈中 ,遇到运算符就弹出两个元素,进行运算,先弹出的元素在左,后弹出的元素在右。

代码及注释

#define ElemType int  // 定义元素类型为整数
typedef struct StackNode{  // 定义栈节点结构
    ElemType data;  // 数据域
    struct StackNode* next;  // 指针域
}StackNode, *LinkStack;  // 栈节点类型定义为指向栈节点的指针
LinkStack initialize(void){  // 初始化栈
    LinkStack temp = (StackNode*)malloc(sizeof(StackNode));  // 分配内存
    temp->next = NULL;  // 初始化栈顶指针
    return temp;  // 返回栈顶指针
}
void StackPush(LinkStack Stack, ElemType data){  // 入栈操作
    StackNode* temp = (StackNode*)malloc(sizeof(StackNode));  // 创建新节点
    temp->data = data;  // 赋值
    temp->next = Stack->next;  // 新节点入栈
    Stack->next = temp;  // 栈顶指针指向新节点
}
bool StackEmpty(LinkStack Stack){  // 判断栈是否为空
    if(Stack->next == NULL)  // 栈顶指针为空
        return true;  // 栈为空
    return false;  // 栈非空
}
bool StackPop(LinkStack Stack, ElemType* data){  // 出栈操作
    if(StackEmpty(Stack))  // 判断栈是否为空
        return false;  // 栈空,出栈失败
    *data = Stack->next->data;  // 获取出栈数据
    StackNode* temp = Stack->next;  // 临时保存出栈节点
    Stack->next = temp->next;  // 栈顶指针指向下一个节点
    free(temp);  // 释放出栈节点内存
    return true;  // 出栈成功
}
int evalRPN(char** tokens, int tokensSize) {  // 逆波兰表达式求值
    int number1, number2;  // 临时变量
    LinkStack stack = initialize();  // 初始化栈
    for(int i = 0; i < tokensSize; i++){  // 遍历表达式
        if( strcmp(tokens[i], "-") == 0 ){  // 减法
            StackPop(stack, &number1);  // 出栈操作
            StackPop(stack, &number2);  // 出栈操作
            StackPush(stack, number2 - number1);  // 入栈操作
        }
        else if( strcmp(tokens[i], "+") == 0 ){  // 加法
            StackPop(stack, &number1);  // 出栈操作
            StackPop(stack, &number2);  // 出栈操作
            StackPush(stack, number2 + number1);  // 入栈操作
        }
        else if( strcmp(tokens[i], "*") == 0 ){  // 乘法
            StackPop(stack, &number1);  // 出栈操作
            StackPop(stack, &number2);  // 出栈操作
            StackPush(stack, number2 * number1);  // 入栈操作
        }
        else if( strcmp(tokens[i], "/") == 0 ){  // 除法
            StackPop(stack, &number1);  // 出栈操作
            StackPop(stack, &number2);  // 出栈操作
            StackPush(stack, number2 / number1);  // 入栈操作
        }
        else{  // 数字
            int number = atoi(tokens[i]);  // 将字符串转换为整数
            StackPush(stack, number);  // 入栈操作
        }
    }
    int result;  // 最终结果
    StackPop(stack, &result);  // 获取栈顶元素
    return result;  // 返回结果
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值