【有效的括号】利用栈来解决经典问题

本文目录

前言

例题

算法思想

算法举例

运行结果

实现代码

核心算法代码

全部运行代码


前言

刚学习了数据结构中的一种类型----栈,我们可以利用他来解决一些比较经典的题目,比如括号匹配问题。刚刷了一道类似题,现在来写篇文章梳理下。

还没有学习栈该如何创建的同学请移步

本篇文章使用的相关代码:数据结构----栈

例题

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

有效字符串需满足

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。

来源:力扣(LeetCode)
链接:OJ链接----Leetcode

示例 1:

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

示例 2:

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

示例 3:

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

示例 4:

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

示例 5:

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

算法思想

S1:遍历输入的括号序列,如果是左括号,进入S2;如果是右括号,进入S3。
S2:将当前遍历到的括号入栈。
S3:出栈一个元素,看其是否与当前的右括号组成一对,如果不是,匹配失败。当然,如果来到此过程中的是一个空栈,匹配也得宣布失败。
S4:循环以上步骤,当括号序列走到 '\0' 时,遍历结束。检查栈中是否还有剩余元素,如果有,匹配失败;如果没有,匹配成功。

算法举例

示例 5:

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

我们拿这个示例来说明一下整个算法的过程:

1.首先我们初始化一个栈 

2.遍历括号序列,找左括号

3.以此类推,直到如图所示

 4.遍历到第3个元素 ']' 时,发现为右括号,我们从栈顶出栈一个左括号,即 '[' ,刚好匹配成一对[]

 5.以此类推,第四个元素也是匹配的

6.括号序列遍历完毕,此时栈已经变空了,全部括号匹配成功,返回true

运行结果

结果与预期值一样,代码通过。

实现代码

这里我采用的是数组栈。

核心算法代码

bool isValid(char * s){
    ST st;
    StackInit(&st); // 初始化栈

    while (*s)
    {
        // S1
        if (*s == '{' || *s == '[' || *s == '(') 
        {
            StackPush(&st, *s);
            s++;
        }
        else
        {
            if (StackEmpty(&st))
                return false;

            char top = StackTop(&st);
            StackPop(&st);

            // S2 S3
            if((*s == '}' && top != '{') 
            || (*s == ']' && top != '[')
            || (*s == ')' && top != '('))  
            {
                StackDestroy(&st);
                return false;
            }
            else
            {
                ++s;
            }
        }
    }

    // S4
    bool ret = StackEmpty(&st);

    StackDestroy(&st);
    return ret;
}

全部运行代码

再次提醒,本代码涉及栈的实现函数,想知道栈该如何创建,以及他的相关代码,请移步阅读博主的这篇博客

typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

// 初始化栈
void StackInit(ST* ps);
// 入栈
void StackPush(ST* ps, STDataType data);
// 出栈
void StackPop(ST* ps);
// 获取栈顶元素
STDataType StackTop(ST* ps);
// 获取栈中有效元素个数
int StackSize(ST* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(ST* ps);
// 销毁栈
void StackDestroy(ST* ps);

void StackInit(ST* ps)
{
	assert(ps);

	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

void StackPush(ST* ps, STDataType data)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->a = (STDataType*)realloc(ps->a, newCapacity * sizeof(STDataType));
		if (ps->a == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->capacity = newCapacity;
	}

	ps->a[ps->top++] = data;
}

void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	
	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}

int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool StackEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

void StackDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

bool isValid(char * s){
    ST st;
    StackInit(&st);

    while (*s)
    {
        if (*s == '{' || *s == '[' || *s == '(')
        {
            StackPush(&st, *s);
            s++;
        }
        else
        {
            if (StackEmpty(&st))
                return false;

            char top = StackTop(&st);
            StackPop(&st);

            if((*s == '}' && top != '{') 
            || (*s == ']' && top != '[')
            || (*s == ')' && top != '('))
            {
                StackDestroy(&st);
                return false;
            }
            else
            {
                ++s;
            }
        }
    }

    bool ret = StackEmpty(&st);

    StackDestroy(&st);
    return ret;
}

后续内容等博主继续学习后分享给大家。请大家继续关注,不断督促,共同进步!

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慧天城寻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值