1. 程式人生 > >LeetCode32-最長有效括號

LeetCode32-最長有效括號

最近這兩天有斷更了,大家知道是為什麼嗎?肯定不是因為是我懶哈(大家想要笑也要憋著)這兩天一直在研究回溯法,被折磨的死去活來的。終於是有些收穫了,所以會在這兩天再把我的一些關於解回溯法題目的心得分享出來,希望大家會有些收穫。寫的都會是很通俗易懂的大白話,會教大家怎麼寫遞迴的過程,因為回溯法雖然好用,但是如何寫出這個過程一直很麻煩,因為其抽象性比較高,很容易就被它搞糊塗了。而我這兩天在網上找的資料都是千篇一律,基本上都是把一些現貨炒來炒去,害人不淺!!!大家敬請期待我的文章。


32-最長有效括號

給定一個只包含 '(' 和 ')' 的字串,找出最長的包含有效括號的子串的長度。

示例 1:

輸入: "(()"
輸出: 2
解釋: 最長有效括號子串為 "()"
示例 2:

輸入: ")()())"
輸出: 4
解釋: 最長有效括號子串為 "()()"

這一題算是20題有效的括號進階版了,因為是要求最長的,所以我們必須是得儲存一個字串中所有有效括號的長度資訊,再從裡面選取長度最大值即可,這算是最直接的思路了。我第一次也是這樣做的。

思路:

  1. 首先用20題求解有效括號的方法(進棧出棧)求得給定字串中所有有效括號的成對下標值,並儲存在一List列表中。
  2. 因為成對括號下標可能相鄰也可能相差大於1,但是下標排序後連續且相差1的下標串對應的字串必然是合法結構,所以我只需要將1中得到的列表中的值做sort()排序操作。
  3. 依次檢查相鄰下標值相差為1的下標最大個數,取最大值即為所求的最長有效括號的長度

程式碼如下:

class Solution:
    # 本題還是採用較典型的進棧出棧法
    # 字典再新增元素時key值並不是按照從小到大排列的,順序是混亂的
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s) == 0 or len(s) == 1:
            return 0
        s_list = list(s)
        # 定義一個字典用做棧,方便做進棧入棧操作,字典key值為括號對應的下標值,value值為相應的括號
        s_queue = {0: s[0]}
        # 定義一個List列表用於儲存一對有效括號的兩個下標值
        max_s_length = []
        for s_index in range(1, len(s_list)):
            # 只有當元素為')'才能出棧,此時要比較棧頂元素,
            # 如果棧頂元素也就是s_queue[s_queue_lastkey]為'('則可以出棧,反之則不行
            if len(s_queue) > 0 and s_list[s_index] == ")":
                # 字典再新增元素時key值並不是按照從小到大排列的,順序是混亂的,所以一定要把key值排序
                # 這樣才能每次拿到s_queue字典最後一個值,也就是棧頂元素
                s_queue_keys = list(s_queue.keys())
                s_queue_keys.sort()
                s_queue_lastkey = s_queue_keys[-1]
                print("s_queue_lastkey", s_queue_lastkey)
                # 如果棧頂元素也就是s_queue[s_queue_lastkey]為'('則可以出棧
                if s_queue[s_queue_lastkey] == "(":
                    print("[s_queue_lastkey, s_index]", [s_queue_lastkey, s_index])
                    max_s_length.extend([s_queue_lastkey, s_index])
                    s_queue.pop(s_queue_lastkey)
            # 只有當元素為'('才能進棧,也就是s_queue字典才能儲存該key值
            else:
                s_queue[s_index] = s_list[s_index]
                print("s_queue", s_queue)
        # 有效括號的下標值得到後排序,並對裡面相鄰的值檢查,即可得到最大長度值
        # 關鍵:成對括號下標可能相鄰也可能相差大於1,但是下標排序後連續且相差1的下標串對應的字串必然是合法結構
        max_s_length.sort()
        if len(max_s_length) == 0:
            return 0
        print("max_s_length", max_s_length)
        length = 1
        max_length = 0
        # 遍歷max_s_length列表,尋找相差為1的下標的最大個數
        for index in range(1, len(max_s_length)):
            if max_s_length[index] - max_s_length[index-1] == 1:
                length += 1
            else:
                if length > max_length:
                    max_length = length
                length = 1
        return max(length, max_length)


if __name__ == "__main__":
    s = "))(((()()"
    result = Solution().longestValidParentheses(s)
    print(result)

這段程式碼中我做了很多註解,大家應該挺好看懂的,但是執行效率挺差的,只有10%左右。

 

後來在網上看到了一大佬給的演算法,也是採用進棧出棧法,但是它是直接將有效括號對的下標值進行運算得到最大有效長度,真的是牛逼,不知道大佬們是怎麼能想到這麼簡單快捷的騷操作,我也把程式碼貼出來,大家可以學習學習。

class Solution:
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        tl = len(s)
        stack = []
        st = 0
        maxlen = 0
        for i in range(tl):
            # 如果是左括號,直接入stack
            if s[i] == '(':
                stack.append(i)
            # 如果右括號
            else:
                # 如果stack裡沒有元素匹對,說明有效括號已經結束,更新起始位置
                if len(stack) == 0:
                    st = i + 1
                    continue
                # 有元素匹對
                else:
                    a = stack.pop()
                    # pop出一個左括號匹對
                    # 如果此時沒了,不能保證不繼續有效括號,所以根據當前的最長距離去更新maxlen
                    if len(stack) == 0:
                        maxlen = max(i - st + 1, maxlen)
                    # 如果此時還有 則計算與棧頂的索引相減來計算長度
                    else:
                        maxlen = max(i - stack[-1], maxlen)

        return maxlen


if __name__ == "__main__":
    s = "))(((()()"
    result = Solution().longestValidParentheses(s)
    print(result)

執行效率也是真的高,再次跪拜大佬!!!