20. 有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例1:
输入: s = " ( ) "
输出:true
示例2:
输入: s = " ( ) [ ] { } "
输出: true
示例3:
输入: s = " ( ] "
输出: false
提示
· 1 <= s.length <= 10 ^ 4
· s 仅由括号 ‘ () [ ] { } ’ 组成
bool isValid (char* s){
}
分析:
这道题可以用栈来写,但是目前还未学习C++,所以只能先手撕一个栈。
如果是左括号,进栈;如果是右括号,出栈里的左括号,进行匹配,匹配失败返回false。
题解:
//栈的操作
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<malloc.h>
#include<stdlib.h>
typedef int STDataType;
#define CAPACITY 4
typedef struct Stack {
int* s;
int top;
int capacity;
}ST;
void STInit(ST* ps);//栈的初始化
void STDestroy(ST* ps);//栈的销毁
bool STEmpty(ST* ps);//判断栈是否为空
void STPush(ST* ps, STDataType x);//进行插入数据
void STPop(ST* ps);//删除数据
STDataType STTop(ST* ps);//寻找栈顶的数据
int STSize(ST* ps);//查看栈有几个元素
void STInit(ST* ps)
{
assert(ps);//栈不能为空
ps->s = (STDataType*)malloc(sizeof(STDataType) * CAPACITY);//malloc开辟空间
if (ps->s == NULL)
{
perror("malloc fail");//开辟失败报错
return;
}
ps->top = 0;//将top置为0,代表数据的个数。赋值为多少无所谓,看个人习惯
ps->capacity = CAPACITY;//将容量先置为空
}
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
void STDestroy(ST* ps)
{
assert(ps);
free(ps->s);//释放空间
ps->s = NULL;//同时将指针置为空
ps->top = 0;
ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
//要先检查容量,判断为不为满,满了进行扩容
//如果扩容步骤使用很多次,就可以写个扩容函数,只有一次就没必要
if (ps->top == ps->capacity)
{
STDataType* new = (STDataType*)realloc(ps->s, sizeof(STDataType) * ps->capacity * 2);
if (new == NULL)
{
perror("realloc fail");
return;
}
ps->s = new;
ps->capacity *= 2;
}
ps->s[ps->top] = x;
ps->top++;
}
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));//如果栈为空的话,就不能进行删除
ps->top--;//直接将个数减一就行了
}
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->s[ps->top - 1];//返回元素减一的数据
}
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
//申请了动态空间要返回操作系统
//思路:遇到左括号就进栈,遇到右括号进行出栈匹配,若匹配失败返回false,直至字符指针指向空
bool isValid(char * s){
ST st;
STInit(&st);
while (*s)
{
//遇到左括号进栈
if (*s == '('
|| *s == '['
|| *s == '{')
{
STPush(&st, *s);
}
//遇到右括号出栈
else
{
//如果第一个符号为右括号则直接返回false
if (STEmpty(&st))
{
STDestroy(&st);
return false;
}
//栈顶元素与右括号进行匹配
if ((STTop(&st) != '(' && *s == ')')
||(STTop(&st) != '[' && *s == ']')
||(STTop(&st) != '{' && *s == '}'))
{
STDestroy(&st);
return false;
}
//匹配成功就要删除栈顶元素,指向下一个元素
STPop(&st);
}
s++;
}
//如果只有一个左括号,就要判断栈里面是否为空,判空函数类型为bool类型
//为空返回true,正好是正确的
//不为空返回false,是错误的
bool ret = STEmpty(&st);
STDestroy(&st);
return ret;
232. 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可
示例1:
输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
提示:
1 <= x <= 9
最多调用 100 次 push、pop、peek 和 empty
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)
分析:
队列的性质是先进先出,栈的性质是后进先出,所以利用两个栈来实现队列的性质就可以了。例子:如果插入数据1 2 3 4,输出数据1 2 3 4,如何使栈实现这样的操作呢?
我们可以1 2 3 4存入到一个栈中,当要出数据时,存入另一个栈中,两个栈分别作为入栈和出栈的功能。
题解:
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<malloc.h>
#include<stdlib.h>
typedef int STDataType;
#define CAPACITY 4
typedef struct Stack {
int* s;
int top;
int capacity;
}ST;
void STInit(ST* ps);//栈的初始化
void STDestroy(ST* ps);//栈的销毁
bool STEmpty(ST* ps);//判断栈是否为空
void STPush(ST* ps, STDataType x);//进行插入数据
void STPop(ST* ps);//删除数据
STDataType STTop(ST* ps);//寻找栈顶的数据
int STSize(ST* ps);//查看栈有几个元素
void STInit(ST* ps)
{
assert(ps);//栈不能为空
ps->s = (STDataType*)malloc(sizeof(STDataType) * CAPACITY);//malloc开辟空间
if (ps->s == NULL)
{
perror("malloc fail");//开辟失败报错
return;
}
ps->top = 0;//将top置为0,代表数据的个数。赋值为多少无所谓,看个人习惯
ps->capacity = CAPACITY;//将容量先置为空
}
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
void STDestroy(ST* ps)
{
assert(ps);
free(ps->s);//释放空间
ps->s = NULL;//同时将指针置为空
ps->top = 0;
ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
//要先检查容量,判断为不为满,满了进行扩容
//如果扩容步骤使用很多次,就可以写个扩容函数,只有一次就没必要
if (ps->top == ps->capacity)
{
STDataType* new = (STDataType*)realloc(ps->s, sizeof(STDataType) * ps->capacity * 2);
if (new == NULL)
{
perror("realloc fail");
return;
}
ps->s = new;
ps->capacity *= 2;
}
ps->s[ps->top] = x;
ps->top++;
}
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));//如果栈为空的话,就不能进行删除
ps->top--;//直接将个数减一就行了
}
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->s[ps->top - 1];//返回元素减一的数据
}
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
typedef struct {
ST emptyst;
ST nonemptyst;
} MyQueue;
//队列的初始化
MyQueue* myQueueCreate() {
MyQueue* newQueue = (MyQueue*)malloc(sizeof(MyQueue));
if (newQueue == NULL)
{
perror("malloc fail");
return NULL;
}
//对栈进行初始化
STInit(&newQueue->emptyst);
STInit(&newQueue->nonemptyst);
return newQueue;
}
//固定一个栈插入数据
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->nonemptyst, x);
}
int myQueuePop(MyQueue* obj) {
//如果出数据的栈为空,那么就要移除数据
if (STEmpty(&obj->emptyst))//不加这个条件就会顺序混乱
{
while (STSize(&obj->nonemptyst))
{
STPush(&obj->emptyst, STTop(&obj->nonemptyst));
STPop(&obj->nonemptyst);
}
}
//不为空,直接出栈
int top = STTop(&obj->emptyst);
STPop(&obj->emptyst);
return top;
}
int myQueuePeek(MyQueue* obj) {
//出数据的栈为空,那么就要进行移数据
if (STEmpty(&obj->emptyst))
{
while (STSize(&obj->nonemptyst))
{
STPush(&obj->emptyst, STTop(&obj->nonemptyst));
STPop(&obj->nonemptyst);
}
}
return STTop(&obj->emptyst);
}
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->emptyst) && STEmpty(&obj->nonemptyst);
}
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->emptyst);
STDestroy(&obj->nonemptyst);
free(obj);
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/