力扣第20题
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
基本算法
首先这是个栈的问题,头插法建立链表就是建栈的过程
栈的数据结构
struct node{
char data;
struct node *next;
};
struct stack{
struct node *top;
struct node *buttom;
};
建立一个新栈
struct stack *create_stack(){
struct stack *sk=(struct stack *)malloc(sizeof(struct stack))
if(sk==NULL){
return false;
}
sk->top=sk->buttom;
return sk;
}
入栈
把top指针指向添加的节点,而且要让新节点的next指向之前top指向的节点
void push(struct stack *sk,char p){
node *n=new node;
n->data=p;
n->next=sk->top;
sk->top=n;
}
出栈
出栈一般有两种:1.让指定数据出栈2.让top指向的数据出栈,注意,如果要让指定的数据出栈,而且如果那个数据在中间,那你就不得不把从top到那个数据的全部节点出栈,因为栈是后进先出,而且只允许一段入/出,这里我们讨论把top指向的节点出栈
这个非常简单,你可能会马上想到
sk->top=sk->top->next;
但是如果再想一下,你虽然完成了出栈,但是出了栈的那个节点怎么办?如果你不delete它它就会一直在堆中,每出栈一次就有一个无用节点占用内存,所以我们还要设法把这个无用节点删除,因此我们需要引入一个临时变量
void pop(struct stack *sk){
node *n=sk->top;
sk->top=n->next;
free(n);
}
挨个取字符串内的字符
for(int i=0;s[i];i++){
l->data=s[i];
printf("%c",s[i]);
struct Lnode *l2=(struct Lnode*)malloc(sizeof(struct Lnode));
l2->next=l;
l=l2;
}
解题思路
此题用链栈来解决
struct node{
char data;
struct node *next;
};
struct stack{
struct node *top;
struct node *buttom;
};
struct stack* create_stack(){
struct stack* sk=(struct stack *)malloc(sizeof(struct stack));
sk->top=sk->buttom;
return sk;
}
struct stack* push(struct stack* sk,char p){
struct node *n=(struct node *)malloc(sizeof(struct node));
n->data=p;
n->next=sk->top;
sk->top=n;
return sk;
}
struct stack* pop(struct stack* sk){
struct node *n=sk->top;
sk->top=n->next;
free(n);
return sk;
}
bool isEmpty(struct stack *sk){
if(sk->top==sk->buttom) return true;
else return false;
}
bool isValid(char * s){
struct stack *l;
l=create_stack();
bool is=true;
int k=0,j=0;
while(s[k]){
k++;
}
for(int i=0;s[i];i++){
if((s[i]=='(')||(s[i]=='{')||(s[i]=='[')){
l=push(l,s[i]);
}
else if(s[i]==')'){
if(!isEmpty(l)){
if(l->top->data!='('){
is=false;break;
}
else l=pop(l);
}
else{
is=false;break;
}
}
else if(s[i]==']'){
if(!isEmpty(l)){
if(l->top->data!='['){
is=false;break;
}
else l=pop(l);
}
else{
is=false;break;
}
}
else if(s[i]=='}'){
if(!isEmpty(l)){
if(l->top->data!='{'){
is=false;break;
}
else l=pop(l);
}
else{
is=false;break;
}
}
j++;
}
if(k==j)is=isEmpty(l);
else false;
return is;
}
大神思路
算法原理
- 栈先入后出特点恰好与本题括号排序特点一致,即若遇到左括号入栈,遇到右括号时将对应栈顶左括号出栈,则遍历完所有括号后 stack 仍然为空;
- 建立哈希表 dic 构建左右括号对应关系:keykey 左括号,valuevalue 右括号;这样查询 22 个括号是否对应只需 O(1)O(1) 时间复杂度;建立栈 stack,遍历字符串 s 并按照算法流程一一判断。
python
class Solution:
def isValid(self, s: str) -> bool:
dic = {'{': '}', '[': ']', '(': ')', '?': '?'}
stack = ['?']
for c in s:
if c in dic: stack.append(c)
elif dic[stack.pop()] != c: return False
return len(stack) == 1
链接:https://leetcode-cn.com/problems/valid-parentheses/solution/valid-parentheses-fu-zhu-zhan-fa-by-jin407891080/