前言
括號匹配問題算是棧應用中比較經典的問題了,在數據結構的書中還有各種考試中會出現。最近刷題的時候也遇到了,就想寫一篇文章整理一下。
例題
題目來自Leetcode中國
給定一個只包括 (
,)
,{
,}
,[
,]
的字符串,判斷字符串是否有效。
有效字符串需滿足:
1、左括號必須用相同類型的右括號閉合。
2、左括號必須以正確的順序閉合。
注意空字符串可被認爲是有效字符串。
示例 1:
輸入: “()”
輸出: true
示例 2:
輸入: “()[]{}”
輸出: true
示例 3:
輸入: “(]”
輸出: false
示例 4:
輸入: “([)]”
輸出: false
示例 5:
輸入: “{[]}”
輸出: true
算法思想
S1:遍歷輸入的括號序列,如果是左括號,進入S2
,如果是右括號,進入S3
S2:如果當前遍歷到左括號,則入棧
S3:如果當前遍歷到右括號,則出棧一個元素,看其是否與當前的右括號組成一對,如果不是,則匹配失敗。或者在出棧過程中發生異常(從空棧中出棧),也匹配失敗
S4:若能順利遍歷完成,檢查棧中是否還有剩餘元素,如果有,則匹配失敗;如果沒有,則匹配成功。
算法舉例
下面以(({[]})
序列爲例說明算法過程:
1、首先將這個字符串轉換成字符數組,並初始化一個空棧。
2、遍歷到第0個元素,(
,爲左括號,入棧
3、後面以此類推,遍歷完第3個元素[
後,棧空間應該是這樣的
4、遍歷到第4個元素]
時,發現爲右括號,此時,從棧頂出棧一個左括號,即[
,剛好[
與]
,匹配成一對
5、以此類推,直到第6個元素)
,都是匹配的
6、此時,序列已經遍歷完畢,但是棧不是空的,所以原序列匹配失敗。
代碼
棧類
這裏我使用了鏈棧,鏈表就沒有自己寫了,用了Java現成的LinkedList<T>
/**
* 棧類,這裏使用鏈棧
*/
class MyStack{
private int num;
private LinkedList<Character> data;
public MyStack(){
this.num = 0;
data = new LinkedList<Character>();
}
/**
* 判斷棧是否爲空
* @return
*/
public boolean isEmpty(){
return num == 0 ? true : false;
}
/**
* 入棧
* @param ch
*/
public void push(Character ch){
this.data.add(ch);
this.num++;
}
/**
* 出棧
* @return
*/
public Character pop(){
//棧爲空時,返回' '
if(this.isEmpty()){
return ' ';
}
Character ch = this.data.remove(data.size()-1);
this.num--;
return ch;
}
}
括號匹配核心算法
/**
* 核心方法
* @param s
* @return
*/
public boolean isValid(String s) {
char[] temp = s.toCharArray();
MyStack stack = new MyStack();
boolean flag = true;
for(int i = 0 ; i < temp.length ; i++){
//左括號,入棧
if(temp[i] == '(' || temp[i] == '{' || temp[i] == '['){
stack.push(temp[i]);
}
else{
//右括號,出棧
char left = stack.pop();
//如果從棧中取出空值,說明棧已空,但還有右括號存在,肯定不匹配
if(left == ' ') {
flag = false;
}
//如果左右括號不匹配,則失敗
if(!check(left,temp[i])){
flag = false;
}
}
}
//循環完畢後,若棧不空,說明左括號個數大於右括號,不匹配
if(flag){
if(!stack.isEmpty()){
flag = false;
}
}
return flag;
}
}
完整代碼
import java.util.LinkedList;
/**
* 括號匹配問題(Blog)
*/
/**
* 棧類,這裏使用鏈棧
*/
class MyStack{
private int num;
private LinkedList<Character> data;
public MyStack(){
this.num = 0;
data = new LinkedList<Character>();
}
/**
* 判斷棧是否爲空
* @return
*/
public boolean isEmpty(){
return num == 0 ? true : false;
}
/**
* 入棧
* @param ch
*/
public void push(Character ch){
this.data.add(ch);
this.num++;
}
/**
* 出棧
* @return
*/
public Character pop(){
//棧爲空時,返回' '
if(this.isEmpty()){
return ' ';
}
Character ch = this.data.remove(data.size()-1);
this.num--;
return ch;
}
}
class Solution {
/**
* 判定左右括號是否匹配
* @param left
* @param right
* @return
*/
private boolean check(char left , char right){
if(left == '('){
return right == ')' ? true : false;
}
if(left == '['){
return right == ']' ? true : false;
}
if(left == '{'){
return right == '}' ? true : false;
}
return false;
}
/**
* 核心方法
* @param s
* @return
*/
public boolean isValid(String s) {
char[] temp = s.toCharArray();
MyStack stack = new MyStack();
boolean flag = true;
for(int i = 0 ; i < temp.length ; i++){
//左括號,入棧
if(temp[i] == '(' || temp[i] == '{' || temp[i] == '['){
stack.push(temp[i]);
}
else{
//右括號,出棧
char left = stack.pop();
//如果從棧中取出空值,說明棧已空,但還有右括號存在,肯定不匹配
if(left == ' ') {
flag = false;
}
//如果左右括號不匹配,則失敗
if(!check(left,temp[i])){
flag = false;
}
}
}
//循環完畢後,若棧不空,說明左括號個數大於右括號,不匹配
if(flag){
if(!stack.isEmpty()){
flag = false;
}
}
return flag;
}
}
public class Main {
public static void main(String[] args) {
// write your code here
Solution solution = new Solution();
System.out.println(solution.isValid("(({[]})"));
}
}
運行結果
(({[]})
的運行結果
false
Process finished with exit code 0
與我們之前預測的一致。