讓我們一起啃演算法----有效的括號

三斤和他的喵發表於2020-04-16

有效括號(Valid-Parentheses)

題幹如下:

給定一個只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字串,判斷字串是否有效。
有效字串需滿足:
  1.左括號必須用相同型別的右括號閉合。
  2.左括號必須以正確的順序閉合。
  3.注意空字串可被認為是有效字串。
示例 1:
  輸入: “()”
  輸出: true
示例 2:
  輸入: “()[]{}”
  輸出: true
示例 3:
  輸入: “(]”
  輸出: false
示例 4:
  輸入: “([)]”
  輸出: false
示例 5:
  輸入: “{[]}”
  輸出: true
來源:力扣

解題思路

這題是我大學老師教 這種資料結構的應用場景時講解的題目,稍微有一丟丟懷念:smile:
解題思路很簡單:從左到右遍歷字串,遇到 左括號: [ ( { ** 就壓入棧中,遇到 **右括號: ] ) } 就拿 棧頂元素當前元素 匹配,是否是一對括號。是,則繼續遍歷,不是,則直接返回 false

注:
  1. 是一種很常見的資料結構,特點是先進後出
  2. 棧頂元素 每次比較之後都要從棧中移除,即 pop 操作
  3. 為什麼是遇到 左括號 將其壓入棧中呢?假設我們將 右括號 壓入棧中,由於我們是從左往右遍歷的,當遇到 左括號 時假設我們取出棧頂元素 右括號 進行比較,這時候有一個問題:當前比較的 左括號 的位置其實是在 右括號 之後的,即類似 ][
聰明的小夥伴一定猜到了,當我們從右向左遍歷時,壓入棧的就是 右括號 啦。

流程圖如下:

程式碼實現

由於需要基於 這種資料結構來解題,我簡單用 go 實現了一個棧:

type Stack struct {
    stack []byte // 存放位元組
    length int // 內部維護的長度
}

// 壓棧
func (s *Stack) push(b byte) {
    s.stack = append(s.stack,b)
    s.length ++
}

// 出棧
func (s *Stack) pop() (res byte) {
    if s.length <= 0 {
        return
    }
    s.length --
    res = s.stack[s.length]
    s.stack = s.stack[0:s.length]
    return
}

// 判斷棧是否為空
func (s *Stack) isEmpty() bool {
    return s.length <= 0
}

// 構造
func getStack() *Stack {
    return &Stack{
    }
}

下面的程式碼實現,基於上面的資料結構:

func isValid(s string) bool {
    if len(s) <= 0 {
        return true
    }
    // 例項化棧
    stack := getStack()
    for i := 0; i < len(s); i++ {
        // 判斷是左括號就壓入棧
        if s[i] == '(' || s[i] == '[' || s[i] == '{' {
            stack.push(s[i])
        } else {
            // 如果棧為空,這時候 i 沒有越界,則返回 false
            if stack.isEmpty() {
                return false
            }
            // 獲取棧頂元素
            top := stack.pop()
            // 比較是否匹配
            if '(' == top && s[i] != ')' || '[' == top && s[i] !=']' || '{' == top && s[i] !='}'{
                return false
            }
        }
    }
    // 如果 i 越界,並且 棧 為空,則返回 true
    if stack.isEmpty() {
        return true
    }
    return false
}

擴充套件思路

在用 解題的過程中會發現: 如果字串是有效括號,那麼一
定存在一對相鄰的括號,並且第一個匹配的右括號,左邊的元素一定是
相對應的左括號。

基於上面的認知,我們將這對相鄰的括號替換成空字串,剩下的字串,如果是有效字串,仍會存在一對相鄰的括號,同理再替換,依次迴圈。如果不存在一對相鄰的括號,並且最後剩下的字串為空了,那麼原始字串就是有效括號,否則不是。

流程圖如下:

具體的程式碼實現如下:( 只是提供一種思路,這種實現方式時間複雜度有點高

func isValidOther(s string) bool {

   // 判斷是否有一對相鄰的括號
  for strings.Index(s,"()") != -1 || strings.Index(s,"[]") != -1 || strings.Index(s,"{}") != -1 {

      // 存在,則替換成 空字串, 繼續下次判斷
  s = strings.Replace(s,"()","",-1)
      s = strings.Replace(s,"[]","",-1)
      s = strings.Replace(s,"{}","",-1)
   }

   // 如果不存在一對相鄰的括號,並且剩餘的字串長度不為0,則返回 false
  if len(s) >= 1 {
      return false
  }
   return true
}

總結

每天進步一點點,加油!
演算法教程專案,每天更新一題,點個 star 支援一下呀
https://github.com/wx-satellite/learning-a...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

三斤

相關文章