題目:
給定一個只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判斷字符串是否有效。
有效字符串需滿足:
左括號必須用相同類型的右括號閉合。
左括號必須以正確的順序閉合。
每個右括號都有一個對應的相同類型的左括號。
示例 1:
輸入:s = “()”
輸出:true
示例 2:
輸入:s = “()[]{}”
輸出:true
示例 3:
輸入:s = “(]”
輸出:false
示例 4:
輸入:s = “([])”
輸出:true
提示:
1 <= s.length <= 104
s 僅由括號 ‘()[]{}’ 組成
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>// 定義鏈表節點結構體
// 每個節點包含一個字符數據和一個指向下一個節點的指針
typedef struct Node
{char data; // 存儲字符數據struct Node *next; // 指向下一個節點的指針
} Node;// 定義棧結構體
// 棧使用鏈表實現,top 指針指向棧頂節點
typedef struct
{Node* top; // 棧頂指針
} Stack;// 初始化棧
// 該函數將棧的 top 指針置為 NULL,表示棧為空
void initStack(Stack* s)
{s->top = NULL; // 將棧頂指針置為 NULL
}// 判斷棧是否為空
// 如果棧的 top 指針為 NULL,則棧為空,返回 1;否則返回 0
int isEmpty(Stack* s)
{return s->top == NULL; // 判斷棧頂指針是否為 NULL
}// 入棧操作
// 該函數將一個字符壓入棧中
void push(Stack* s, char value)
{// 為新節點分配內存Node* newnode = (Node*)malloc(sizeof(Node));if (newnode == NULL){// 內存分配失敗,輸出錯誤信息printf("內存分配失敗!");return;}newnode->data = value; // 將數據存入新節點newnode->next = s->top; // 新節點的 next 指針指向原棧頂節點s->top = newnode; // 更新棧頂指針為新節點
}// 出棧操作
// 該函數將棧頂元素彈出
void pop(Stack* s)
{if (isEmpty(s)){// 棧為空,輸出錯誤信息printf("棧為空");return;}Node* temp = s->top; // 臨時指針指向棧頂節點char value = temp->data; // 獲取棧頂節點的數據s->top = s->top->next; // 更新棧頂指針為原棧頂節點的下一個節點free(temp); // 釋放原棧頂節點的內存
}// 判斷字符串中的括號是否有效
// 該函數使用棧來檢查字符串中的括號是否匹配
bool isValid(char* s) {Stack stack;initStack(&stack); // 初始化棧int n = strlen(s); // 獲取字符串的長度for (int i = 0; i < n; i++){if (s[i] == '(' || s[i] == '{' || s[i] == '[')// 如果是左括號,直接入棧push(&stack, s[i]);else if (s[i] == ')' && stack.top && stack.top->data == '(')// 如果是右括號且棧不為空,并且棧頂元素是對應的左括號,則出棧pop(&stack);else if (s[i] == ']' && stack.top && stack.top->data == '[')// 如果是右括號且棧不為空,并且棧頂元素是對應的左括號,則出棧pop(&stack);else if (s[i] == '}' && stack.top && stack.top->data == '{')// 如果是右括號且棧不為空,并且棧頂元素是對應的左括號,則出棧pop(&stack);else// 其他情況,將字符入棧push(&stack, s[i]);}if (stack.top)// 如果棧不為空,說明有括號不匹配,返回 falsereturn false;else// 如果棧為空,說明所有括號都匹配,返回 truereturn true;
}
代碼分析:
邏輯清晰:代碼結構清晰,將棧的基本操作(初始化、入棧、出棧、判斷是否為空)封裝成獨立的函數,提高了代碼的可讀性和可維護性。isValid 函數利用棧的特性來判斷括號是否匹配,邏輯簡潔明了。
內存管理:在入棧操作中,會檢查內存分配是否成功,避免了因內存分配失敗而導致的程序崩潰。在出棧操作中,會釋放棧頂節點的內存,避免了內存泄漏。
擴展性:棧的實現使用鏈表,易于擴展。如果需要存儲更多類型的數據,只需要修改 Node 結構體的 data 成員即可。