玩轉演算法面試LeetCode演算法練習——二分搜尋樹
目錄
235. 二叉搜尋樹的最近公共祖先
給定一個二叉搜尋樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”
例如,給定如下二叉搜尋樹: root = [6,2,8,0,4,7,9,null,null,3,5]
_______6______ / \ ___2__ ___8__ / \ / \ 0 _4 7 9 / \ 3 5
輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
輸出: 6
解釋: 節點 2 和節點 8 的最近公共祖先是 6。
輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
輸出: 2
解釋: 節點 2 和節點 4 的最近公共祖先是 2, 因為根據定義最近公共祖先節點可以為節點本身。
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def lowestCommonAncestor(self, root, p, q): """ :type root: TreeNode :type p: TreeNode :type q: TreeNode :rtype: TreeNode """ assert(p != None and q != None) if root == None: return None if p.val < root.val and q.val < root.val: return self.lowestCommonAncestor(root.left, p, q) if p.val > root.val and q.val > root.val: return self.lowestCommonAncestor(root.right, p, q) return root
98. 驗證二叉搜尋樹
給定一個二叉樹,判斷其是否是一個有效的二叉搜尋樹。
假設一個二叉搜尋樹具有如下特徵:
- 節點的左子樹只包含小於當前節點的數。
- 節點的右子樹只包含大於當前節點的數。
- 所有左子樹和右子樹自身必須也是二叉搜尋樹。
示例 1:
輸入:
2
/ \
1 3
輸出: true
示例 2:
輸入:
5
/ \
1 4
/ \
3 6
輸出: false
解釋: 輸入為: [5,1,4,null,null,3,6]。
根節點的值為 5 ,但是其右子節點值為 4 。
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def ValidBST(self,root,min,max): if (root is None): return True elif (root.val <= min or root.val >= max): return False else: return (self.ValidBST(root.left,min,root.val) and self.ValidBST(root.right,root.val,max)) def isValidBST(self, root): """ :type root: TreeNode :rtype: bool """ return self.ValidBST(root,-2**62,2**62)
450. 刪除二叉搜尋樹中的節點
給定一個二叉搜尋樹的根節點 root 和一個值 key,刪除二叉搜尋樹中的 key 對應的節點,並保證二叉搜尋樹的性質不變。返回二叉搜尋樹(有可能被更新)的根節點的引用。
一般來說,刪除節點可分為兩個步驟:
- 首先找到需要刪除的節點;
- 如果找到了,刪除它。
說明: 要求演算法時間複雜度為 O(h),h 為樹的高度。
示例:
root = [5,3,6,2,4,null,7]
key = 3
5
/ \
3 6
/ \ \
2 4 7
給定需要刪除的節點值是 3,所以我們首先找到 3 這個節點,然後刪除它。
一個正確的答案是 [5,4,6,2,null,null,7], 如下圖所示。
5
/ \
4 6
/ \
2 7
另一個正確答案是 [5,2,6,null,4,null,7]。
5
/ \
2 6
\ \
4 7
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
if root == None or key == None:
return root
if key < root.val:
root.left = self.deleteNode(root.left, key)
elif key > root.val:
root.right = self.deleteNode(root.right, key)
else:
if not root.left:
root = root.right
elif not root.right:
root = root.left
else:
tmp = self.find_min(root.right)#可以找右子樹最小值或左子樹最大值
root.val = tmp.val
root.right = self.deleteNode(root.right, tmp.val)
return root
def find_min(self, root):
if root.left:
return self.find_min(root.left)
return root
108. 將有序陣列轉換為二叉搜尋樹
將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。
示例:
給定有序陣列: [-10,-3,0,5,9],
一個可能的答案是:[0,-3,9,-10,null,5],它可以表示下面這個高度平衡二叉搜尋樹:
0
/ \
-3 9
/ /
-10 5
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sortedArrayToBST(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
if not nums:
return None
mid = len(nums) // 2
root = TreeNode(nums[mid])
left = nums[:mid]
right = nums[mid+1:]
root.left = self.sortedArrayToBST(left)
root.right = self.sortedArrayToBST(right)
return root
230. 二叉搜尋樹中第K小的元素
給定一個二叉搜尋樹,編寫一個函式 kthSmallest
來查詢其中第 k 個最小的元素。
說明:
你可以假設 k 總是有效的,1 ≤ k ≤ 二叉搜尋樹元素個數。
示例 1:
輸入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
輸出: 1
示例 2:
輸入: root = [5,3,6,2,4,null,null,1], k = 3
5
/ \
3 6
/ \
2 4
/
1
輸出: 3
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
self.res = []
self.dfs(root)
return self.res[k-1]
#self.dfs_2(root)
#return self.res[-k]
def dfs(self,root):
#中序遍歷對二分搜尋樹(從小到大排序)
if root == None:
return
self.dfs(root.left)
self.res.append(root.val)
self.dfs(root.right)
return self.res
def dfs_2(self,root):
#中序遍歷(改)對二分搜尋樹(從大到小排序)
if root == None:
return
self.dfs_2(root.right)
self.res.append(root.val)
self.dfs_2(root.left)
return self.res
236. 二叉樹的最近公共祖先
給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”
例如,給定如下二叉樹: root = [3,5,1,6,2,0,8,null,null,7,4]
_______3______
/ \
___5__ ___1__
/ \ / \
6 _2 0 8
/ \
7 4
示例 1:
輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。
示例 2:
輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。因為根據定義最近公共祖先節點可以為節點本身。
說明:
所有節點的值都是唯一的。
p、q 為不同節點且均存在於給定的二叉樹中。
思路:
如果root為null,肯定返回null;
如果root的值等於其中的某一個,那麼就返回這個值;
如果root的值和兩個都不相等,遞迴的判斷左右孩子;
如果返回左右孩子的兩個值都不為null,說明root節點的左右子樹中各有一個,返回root即可!
若其中一個為null,說明在一邊的子樹中,返回另一個即可(即首先遍歷到的節點了
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if root == None or root.val == p.val or root.val == q.val:
return root
leftN = self.lowestCommonAncestor(root.left,p,q)
rightN = self.lowestCommonAncestor(root.right,p,q)
if leftN != None and rightN != None:
return root
elif leftN == None:
return rightN;
else:
return leftN;