題目介紹
描述:
給你一個樹,請你 按中序遍歷 重新排列樹,使樹中最左邊的結點現在是樹的根,並且每個結點沒有左子結點,只有一個右子結點。
示例 :
輸入:[5,3,6,2,4,null,8,1,null,null,null,7,9]
5
/ \\
3 6
/ \\ \\
2 4 8
/ / \\
1 7 9
輸出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
1
\\
2
\\
3
\\
4
\\
5
\\
6
\\
7
\\
8
\\
9
提示:
給定樹中的結點數介於 1 和 100 之間。
每個結點都有一個從 0 到 1000 範圍內的唯一整數值。
解題思路:
遞歸算法的關鍵是要明確函數的「定義」是什麼,然後相信這個定義,利用這個定義推導最終結果。
寫樹相關的算法,簡單說就是,先搞清楚當前 root 節點該做什麼,然後根據函數定義遞歸調用子節點,遞歸調用會讓孩子節點做相同的事情。
二叉樹題目的一個難點在於如何通過題目的要求思考出每一個節點需要做什麼
二叉樹解題策略
一 遞歸 二 隊列 + 迭代 (層次遍歷) 三 棧 + 迭代 (非遞歸遍歷) 四 其它
三種基本的遍歷方式,都可以用遞歸來實現。寫遞歸算法的時候,需要注意遞歸退出條件以及遞歸操作的表達。
中序遍歷返回升序數組,並根據題目要求的結構生成樹。
自己的解法實現
def inorder(node):
if not node: return []
return inorder(node.left) + [node.val] + inorder(node.right)
node_list = inorder(root)
new_root = TreeNode(node_list[0])
cur = new_root
for i in range(1, len(node_list)):
cur.right = TreeNode(node_list[i])
cur = cur.right
return new_root
網上比較優秀的解法
解法一
方法一:中序遍歷 + 構造新的樹 我們在樹上進行中序遍歷,就可以從小到大得到樹上的節點。我們把這些節點的對應的值存放在數組中,它們已經有序。接着我們直接根據數組構件題目要求的樹即可
def increasingBST(self, root):
def inorder(node):
if node:
yield from inorder(node.left)
yield node.val
yield from inorder(node.right)
res = cur = TreeNode(None)
for e in inorder(root):
cur.right = TreeNode(e)
cur = cur.right
return res.right
解法二
方法二:中序遍歷 + 更改樹的連接方式 我們在樹上進行中序遍歷,但會將樹中的節點之間重新連接而不使用額外的空間。具體地,當我們遍歷到一個節點時,把它的左孩子設爲空,並將其本身作爲上一個遍歷到的節點的右孩子。
def increasingBST2(self, root):
def inorder(node):
if node:
inorder(node.left)
node.left = None
self.cur.right = node
self.cur = node
inorder(node.right)
res = self.cur = TreeNode(None)
inorder(root)
return res.right
解法三
這是個很經典的中序遍歷的問題。 難點不在遞歸,而在於如何輸出一個只有右子節點的樹? 首先要構造一個TreeNode(),再把已有的TreeNode的子節點指向新的TreeNode節點
def increasingBST3(self, root):
def sort(node, ls):
if not node: return
if node.left:
sort(node.left, ls)
ls.append(node.val)
if node.right:
sort(node.right, ls)
res = []
sort(root, res)
ans = cur = TreeNode(None)
for e in res:
cur.val = e
if e == res[-1]:
break
cur.right = TreeNode(None)
cur = cur.right
return ans
相關知識總結和思考
相關知識:
BFS:廣度/寬度優先。其實就是從上到下,先把每一層遍歷完之後再遍歷一下一層。
可以使用Queue的數據結構。我們將root節點初始化進隊列,通過消耗尾部,插入頭部的方式來完成BFS。
二叉搜索樹(BST)的特性:
- 若它的左子樹不爲空,則所有左子樹上的值均小於其根節點的值
- 若它的右子樹不爲空,則所有右子樹上的值均大於其根節點的值
- 它的左右子樹也分別爲二叉搜索樹
遞歸與迭代的區別
遞歸:重複調用函數自身實現循環稱爲遞歸; 迭代:利用變量的原值推出新值稱爲迭代,或者說迭代是函數內某段代碼實現循環;