題目介紹
描述:
給定一個二叉搜索樹和一個目標結果,如果 BST 中存在兩個元素且它們的和等於給定的目標結果,則返回 true。
案例 1:
輸入:
5
/ \\
3 6
/ \\ \\
2 4 7
Target = 9
輸出: True
案例 2:
輸入:
5
/ \\
3 6
/ \\ \\
2 4 7
Target = 28
輸出: False
解題思路:
遞歸算法的關鍵是要明確函數的「定義」是什麼,然後相信這個定義,利用這個定義推導最終結果。
寫樹相關的算法,簡單說就是,先搞清楚當前 root 節點該做什麼,然後根據函數定義遞歸調用子節點,遞歸調用會讓孩子節點做相同的事情。
二叉樹題目的一個難點在於如何通過題目的要求思考出每一個節點需要做什麼
二叉樹解題策略
一 遞歸 二 隊列 + 迭代 (層次遍歷) 三 棧 + 迭代 (非遞歸遍歷) 四 其它
三種基本的遍歷方式,都可以用遞歸來實現。寫遞歸算法的時候,需要注意遞歸退出條件以及遞歸操作的表達。
自己的解法實現
def __init__(self):
self._dic = {}
def findTarget(self, root, k):
if not root:return False
if k - root.val in self._dic:
return True
self._dic[root.val] = 0
return self.findTarget(root.left, k) or self.findTarget(root.right, k)
網上比較優秀的解法
解法一
BST的性質:中序遍歷是升序數組。
對BST中序遍歷得到中序數組後,因爲數組有序,可利用左右指針來判斷是否存在“兩個元素的和與給定值相同”。
def findTarget2(self, root, k):
def inorder(node):
if not node: return []
return inorder(node.left) + [node.val] + inorder(node.right)
alllist = inorder(root)
left, right = 0, len(alllist) - 1
while left < right:
_sum = alllist[left] + alllist[right]
if _sum == k:
return True
if _sum > k:
right -= 1
if _sum < k:
left += 1
return False
解法二
每訪問一個節點,如果當前值在集合中出現說明滿足條件。 否則存儲k-current.val到集合中。
def findTarget3(self, root, k):
values = set()
def dfs(node):
if not node: return False
if node.val in values:
return True
values.add(k - node.val)
return dfs(node.left) or dfs(node.right)
return dfs(root)
解法三
中序遍歷的過程中用字典存儲已經遍歷過的值
def findTarget4(self, root, k):
stack, curnode = [], root
used = dict()
while stack or curnode:
while curnode:
stack.append(curnode)
curnode = curnode.left
curnode = stack.pop()
if not used:
used[curnode.val] = 1
else:
if k - curnode.val in used:
return True
used[curnode.val] = 1
curnode = curnode.right
return False
相關知識總結和思考
相關知識:
BFS:廣度/寬度優先。其實就是從上到下,先把每一層遍歷完之後再遍歷一下一層。
可以使用Queue的數據結構。我們將root節點初始化進隊列,通過消耗尾部,插入頭部的方式來完成BFS。
二叉搜索樹(BST)的特性:
- 若它的左子樹不爲空,則所有左子樹上的值均小於其根節點的值
- 若它的右子樹不爲空,則所有右子樹上的值均大於其根節點的值
- 它的左右子樹也分別爲二叉搜索樹
遞歸與迭代的區別
遞歸:重複調用函數自身實現循環稱爲遞歸; 迭代:利用變量的原值推出新值稱爲迭代,或者說迭代是函數內某段代碼實現循環;