1
0
mirror of https://github.com/SunnyQjm/algorithm-review.git synced 2026-06-03 08:16:43 +08:00

add: chapter10

This commit is contained in:
2020-06-22 10:08:57 +08:00
parent ff2342f2d6
commit ecca4239b9
4 changed files with 277 additions and 0 deletions
@@ -0,0 +1,74 @@
#!/usr/bin/env python
# coding=utf-8
#######################################################################################
# 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
#
# 示例 1:
# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
# 输出: 6
# 解释: 节点 2 和节点 8 的最近公共祖先是 6。
#
# 示例 2:
# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
# 输出: 2
# 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
#
# 说明:
# - 所有节点的值都是唯一的。
# - p、q 为不同节点且均存在于给定的二叉搜索树中。
#######################################################################################
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def __repr__(self):
if self:
return "{}->{}->{}".format(self.val, repr(self.left), repr(self.right))
class Solution:
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype TreeNode
(knowledge)
思路:
1. 直接根据二叉搜索树的性质,对树进行先序遍历;
2. 将两个目标节点根据节点值得大小,小的指定为left, 大的指定为right
2. 如果找到一个节点,其值大于等于left.val,且小于等于right.val,则该节点即为要求的结果
3. 如果当前节点不是目标节点,则对左右子树进行递归遍历
"""
def preOrderTraversal(root, left, right):
if not root or (left.val <= root.val <= right.val):
return root
leftResult = preOrderTraversal(root.left, left, right)
rightResult = preOrderTraversal(root.right, left, right)
return leftResult if not rightResult else rightResult
left = p if p.val < q.val else q
right = p if p.val >= q.val else q
return preOrderTraversal(root, left, right)
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python
# coding=utf-8
#######################################################################################
# Leetcode 110 平衡二叉树
#
# 给定一个二叉树,判断它是否是高度平衡的二叉树。
# 本题中,一棵高度平衡二叉树定义为:
# 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
#
# 示例 1:
# 给定二叉树 [3,9,20,null,null,15,7]
#
# 3
# / \
# 9 20
# / \
# 15 7
# 返回 true 。
#
# 示例 2:
# 给定二叉树 [1,2,2,3,3,null,null,4,4]
#
# 1
# / \
# 2 2
# / \
# 3 3
# / \
# 4 4
# 返回 false 。
#######################################################################################
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def __repr__(self):
if self:
return "{}->{}->{}".format(self.val, repr(self.left), repr(self.right))
class Solution:
def isBalanced(self, root):
"""
:type root: TreeNode
:rtype bool
(knowledge)
思路:
1. 直接递归计算每个节点左右子树的高度;
2. 根据AVL树的特性,如果任意一个节点的左右子树的高度差大于一,则该树不是AVL树,标记器高度为-1;
3. 如果某个子树的高度计算为-1,则表示该子树不是AVL树,-1会一直传递到顶层。
"""
def preOrderTraversal(root):
if not root:
return 0
leftNum = preOrderTraversal(root.left)
rightNum = preOrderTraversal(root.right)
if leftNum == -1 or rightNum == -1 or abs(leftNum - rightNum) > 1:
return -1
return 1 + max(leftNum, rightNum)
return preOrderTraversal(root) != -1
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python
# coding=utf-8
#######################################################################################
# Leetcode 257 二叉树的所有路径
#
# 给定一个二叉树,返回所有从根节点到叶子节点的路径。
# 说明: 叶子节点是指没有子节点的节点。
#
# 示例:
# 输入:
#
# 1
# / \
# 2 3
# \
# 5
#
# 输出: ["1->2->5", "1->3"]
#
# 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
#######################################################################################
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def __repr__(self):
if self:
return "{}->{}->{}".format(self.val, repr(self.left), repr(self.right))
class Solution:
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype List[str]
(knowledge)
思路:
1. 递归的进行先序遍历,过程中记录走过的路径;
2. 当遍历到一个叶子节点时,将当前路径添加到结果集当中;
"""
def preorderTraversal(root, s, result):
if not root:
return
if not root.left and not root.right:
result.append(s + "->" + str(root.val))
preOrderTraversal(root.left, s + "->" + str(root.val), result)
preOrderTraversal(root.right, s + "->" + str(root.val), result)
if not root:
return []
if not root.left and not root.right:
return [str(root.val)]
s = str(root.val)
result = []
preOrderTraversal(root, s, result)
return result
@@ -0,0 +1,74 @@
#!/usr/bin/env python
# coding=utf-8
#######################################################################################
# Leetcode 703 数据流中的第K大元素
#
# 设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。
# 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。
#
# 示例:
# int k = 3;
# int[] arr = [4,5,8,2];
# KthLargest kthLargest = new KthLargest(3, arr);
# kthLargest.add(3); // returns 4
# kthLargest.add(5); // returns 5
# kthLargest.add(10); // returns 5
# kthLargest.add(9); // returns 8
# kthLargest.add(4); // returns 8
#
# 说明:
# 你可以假设 nums 的长度≥ k-1 且k ≥ 1。
#######################################################################################
import heapq
class KthLargest:
def __init__(self, k, nums):
"""
:type k: int
:type nums: List[int]
"""
self.heap = nums
heapq.heapify(self.heap) # 用一个列表作为堆(使用heapq对其操作)
self.currentSize = len(nums) # 保存当前堆中元素的个数
self.k = k
while self.currentSize > k:
heapq.heappop(self.heap)
self.currentSize -= 1
def add(self, val):
"""
:type val: int
:rtype: int
(knowledge)
思路:
1. 这是堆的应用,每次要返回第K大的元素,则表示我们只要维持当前最大的到第K大的元素即可,更小的可以忽略;
2. 对初始传入的nums进行堆构造,并删除堆顶元素直至堆中元素个数小于等于k时停止;
3. 每次插入时执行以下流程:
- 首先判断当前堆的大小是k还是k-1;(因为题目中指出,nums >= k-1,所以初始堆中元素个数至少为k-1,又因为我们在初始化时进行了堆删除,删到小于等于k为止,所以堆中元素最多有k个)
- 如果currentSize == k-1,则插入当前元素到堆中,并返回堆顶元素即可;
- 如果currentSuze > k-1, 则将当前元素插入到堆中,接着再删除堆顶元素,并返回堆顶元素;(这样可以保证堆中元素一直是k个)
"""
if self.currentSize == self.k - 1:
heapq.heappush(self.heap, val)
self.size += 1
else:
heapq.heappush(self.heap, val)
heapq.heappop(self.heap)
return self.heap[0]
if __name__ == '__main__':
kthLargest = KthLargest(3, [4, 5, 8, 2])
print(kthLargest.add(3), "= 4")
print(kthLargest.add(5), "= 5")
print(kthLargest.add(10), "= 5")
print(kthLargest.add(9), "= 8")
print(kthLargest.add(4), "= 8")