LeetCode0606: 根據二叉樹創建字符串

題目介紹

描述:

你需要採用前序遍歷的方式,將一個二叉樹轉換成一個由括號和整數組成的字符串。

空節點則用一對空括號 "()" 表示。而且你需要省略所有不影響字符串與原始二叉樹之間的一對一映射關係的空括號對。

示例 1:

輸入: 二叉樹: [1,2,3,4]
       1
     /   \\
    2     3
   /    
  4     

輸出: "1(2(4))(3)"

解釋: 原本將是“1(2(4)())(3())”,
在你省略所有不必要的空括號對之後,
它將是“1(2(4))(3)”。
示例 2:

輸入: 二叉樹: [1,2,3,null,4]
       1
     /   \\
    2     3
     \\  
      4 

輸出: "1(2()(4))(3)"

解釋: 和第一個示例相似,
除了我們不能省略第一個對括號來中斷輸入和輸出之間的一對一映射關係。

解題思路:

遞歸算法的關鍵是要明確函數的「定義」是什麼,然後相信這個定義,利用這個定義推導最終結果。

寫樹相關的算法,簡單說就是,先搞清楚當前 root 節點該做什麼,然後根據函數定義遞歸調用子節點,遞歸調用會讓孩子節點做相同的事情。

二叉樹題目的一個難點在於如何通過題目的要求思考出每一個節點需要做什麼

二叉樹解題策略

一 遞歸 二 隊列 + 迭代 (層次遍歷) 三 棧 + 迭代 (非遞歸遍歷) 四 其它

三種基本的遍歷方式,都可以用遞歸來實現。寫遞歸算法的時候,需要注意遞歸退出條件以及遞歸操作的表達。

自己的解法實現

def tree2str6(self, root):
        def construct(node):
            if not node:  # 如果到了空節點返回空字符即可
                return ''
            left_str = construct(node.left)  # 默認獲得左子樹已經括好的內容
            right_str = construct(node.right)  # 默認獲得右子樹已經括好的內容
            if left_str and not right_str:  # 右子樹的內容爲空是不加括號
                return str(node.val) + '(' + left_str + ')'
            elif not left_str and not right_str:  # 左右子樹返回內容逗我空時不加括號
                return str(node.val)
            else:  # 其他情況正常輸出即可
                return str(node.val) + '(' + left_str + ')' + '(' + right_str + ')'

        return construct(root)

網上比較優秀的解法

解法一

方法一:遞歸 我們可以使用遞歸的方法得到二叉樹的前序遍歷。在遞歸時,根據題目描述,我們需要加上額外的括號,會有以下 4 種情況:

  1. 如果當前節點有兩個孩子,那我們在遞歸時,需要在兩個孩子的結果外都加上一層括號;
  2. 如果當前節點沒有孩子,那我們不需要在節點後面加上任何括號;
  3. 如果當前節點只有左孩子,那我們在遞歸時,只需要在左孩子的結果外加上一層括號,而不需要給右孩子加上任何括號;
  4. 如果當前節點只有右孩子,那我們在遞歸時,需要先加上一層空的括號 () 表示左孩子爲空,再對右孩子進行遞歸,並在結果外加上一層括號。
def tree2str(self, root):
        if not root: return ""
        if not root.left and not root.right:
            return str(root.val) + ""
        if not root.right:
            return str(root.val) + "(" + self.tree2str(root.left) + ")"
        return str(root.val) + "(" + self.tree2str(root.left) + ")(" + self.tree2str(root.right) + ")"

解法二

題目的意思是子節點需要用()來包裹。舉例來說,二叉樹[root,left,right],則轉換爲root(left)(right)。如果只有left爲空節點,則輸出root()(right);如果只有right爲空節點則可以忽略右節點的(),輸出爲root(left)。

解題方法: 先序遍歷,並判斷不同情況: (1)如果當前節點爲空,則返回空字符串 (2)如果左子節點非空,右子節點空,則返回str(node.val) + '(' + dfs(node.left) + ')' (3)如果左子節點空,右子節點非空,則返回str(node.val) + '()' + '(' + dfs(node.right) + ')' (4)如果左右子節點都爲空,則返回str(node.val) (5)除上述情況,則左右節點都存在,返回str(node.val) + '(' + dfs(node.left) + ')' + '(' + dfs(node.right) + ')'

def tree2str3(self, root):
        def dfs(node):
            if not node: return ''
            if node.left and not node.right:
                return str(node.val) + '(' + dfs(node.left) + ')'
            if not node.left and node.right:
                return str(node.val) + '()' + '(' + dfs(node.right) + ')'
            if not node.left and not node.right:
                return str(node.val)
            return str(node.val) + '(' + dfs(node.left) + ')' + '(' + dfs(node.right) + ')'
        return dfs(root)

解法三

def tree2str4(self, root):
        path = ''
        def preorder(node):
            nonlocal path
            if not node: return
            path += str(node.val)

            if not node.left and not node.right: return
            path += '('
            preorder(root.left)
            path += ')'

            if node.right:
                path += '('
                preorder(node.right)
                path += ')'
        preorder(root)
        return path

解法四

如果只有左子樹爲空,則輸出root()(right)

如果只有右子樹爲空,則輸出root(left)

def tree2str5(self, root):
        if not root: return ''
        left_str = right_str = ''
        if root.left or root.right:
            left_str = '(' + self.tree2str(root.left) + ')'
            # 只有右子樹存在,才繼續向下遍歷;把右子樹空時的'()'扔了
            if root.right:
                right_str = '(' + self.tree2str(root.right) + ')'
        return str(root.val) + left_str + right_str

相關知識總結和思考

相關知識:

BFS:廣度/寬度優先。其實就是從上到下,先把每一層遍歷完之後再遍歷一下一層。

可以使用Queue的數據結構。我們將root節點初始化進隊列,通過消耗尾部,插入頭部的方式來完成BFS。

二叉搜索樹(BST)的特性:

  1. 若它的左子樹不爲空,則所有左子樹上的值均小於其根節點的值
  2. 若它的右子樹不爲空,則所有右子樹上的值均大於其根節點的值
  3. 它的左右子樹也分別爲二叉搜索樹

遞歸與迭代的區別

遞歸:重複調用函數自身實現循環稱爲遞歸; 迭代:利用變量的原值推出新值稱爲迭代,或者說迭代是函數內某段代碼實現循環;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章