题目编号: 88、100、101、104、107、108、110、111、112
88. 合并两个有序数组
我的解法:
合并后排序
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
for i in range(m,m+n):
nums1[i] = nums2[i-m]
nums1.sort()
return nums1
题解思路:
双指针法:
1.从前往后:
将指针p1 置为 nums1的开头, p2为 nums2的开头,在每一步将最小值放入输出数组中。
由于 nums1 是用于输出的数组,需要将nums1中的前m个元素放在其他地方,也就需要 O(m) 的空间复杂度,时间复杂度为O(m+n)
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead.
"""
# Make a copy of nums1.
nums1_copy = nums1[:m]
nums1[:] = []
# Two get pointers for nums1_copy and nums2.
p1 = 0
p2 = 0
# Compare elements from nums1_copy and nums2
# and add the smallest one into nums1.
while p1 < m and p2 < n:
if nums1_copy[p1] < nums2[p2]:
nums1.append(nums1_copy[p1])
p1 += 1
else:
nums1.append(nums2[p2])
p2 += 1
# if there are still elements to add
if p1 < m:
nums1[p1 + p2:] = nums1_copy[p1:]
if p2 < n:
nums1[p1 + p2:] = nums2[p2:]
2.从后往前:
从前往后已经取得了最优的时间复杂度O(n+m),但需要使用额外空间。这是由于在从头改变nums1的值时,需要把nums1中的元素存放在其他位置。
如果我们从结尾开始改写 nums1 的值又会如何呢?这里没有信息,因此不需要额外空间。
这里的指针 p 用于追踪添加元素的位置。
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead.
"""
# two get pointers for nums1 and nums2
p1 = m - 1
p2 = n - 1
# set pointer for nums1
p = m + n - 1
# while there are still elements to compare
while p1 >= 0 and p2 >= 0:
if nums1[p1] < nums2[p2]:
nums1[p] = nums2[p2]
p2 -= 1
else:
nums1[p] = nums1[p1]
p1 -= 1
p -= 1
# add missing elements from nums2
nums1[:p2 + 1] = nums2[:p2 + 1]
100. 相同的树
我的解法:
首先判断 p 和 q 是不是 None,然后判断它们的值是否相等。
若以上判断通过,则递归对子结点做同样操作。
# 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 isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
if not p and not q:
return True
if not p or not q:
return False
if p.val != q.val:
return False
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
101. 对称二叉树
我的解法:
递归。
递归结束条件:
都为空指针则返回 true
只有一个为空则返回 false
递归过程:
判断两个指针当前节点值是否相等
判断 A 的右子树与 B 的左子树是否对称
判断 A 的左子树与 B 的右子树是否对称
短路:
在递归判断过程中存在短路现象,也就是做 与 操作时,如果前面的值返回 false 则后面的不再进行计算
时间复杂度:O(n)
# 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 isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def check(node1,node2):
if not node1 and not node2:
return True
elif not node1 or not node2:
return False
if node1.val != node2.val:
return False
return check(node1.left,node2.right) and check(node1.right,node2.left)
return check(root,root)
104. 二叉树的最大深度
我的解法:
递归
若当前结点为空,则返回0;若当前节点不为空,则返回左右子树的最大深度+1
# 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 maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right))
107. 二叉树的层次遍历 II
解法思路:
class Solution:
def levelOrderBottom(self, root):
queue = [] # 结果列表
cur = [root] # 接下来要循环的当前层节点,存的是节点
while cur: # 当前层存在结点时
cur_layer_val = [] # 初始化当前层结果列表为空,存的是val
next_layer_node = [] # 初始化下一层结点列表为空
for node in cur: # 遍历当前层的每一个结点
if node: # 如果该结点不为空,则进行记录
cur_layer_val.append(node.val) # 将该结点的值加入当前层结果列表的末尾
next_layer_node.extend([node.left, node.right]) # 将该结点的左右孩子结点加入到下一层结点列表
if cur_layer_val: # 只要当前层结果列表不为空
queue.insert(0, cur_layer_val) # 则把当前层结果列表插入到队列首端
cur = next_layer_node # 下一层的结点变成当前层,接着循环
return queue # 返回结果队列
108. 将有序数组转换为二叉搜索树
我的解法:
递归+二分法
1.平衡二叉搜索树的特点是:每个节点的左右子树都高度差在1以内,每个节点左子树小于右子树。
2.根据平衡二叉搜索树的特点,可以联想到,每个节点当做根节点的时候,左子树形成的数组一定比它小,右子树形成的数组一定比他大。因此,符合有序数组任意子数组中点的性质。
3.结合树结构常用的递归思想,可以采用DFS,递归构建这颗树,为了实现每个节点都是平衡二叉搜索树,可以递归二分数组来分配资源,左面的构建左子树,右面的构建右子树,以此递归。
# 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 sortedArrayToBST(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
if nums is None:
return
start = 0
end = len(nums) - 1
if start > end:
return
mid = (start + end) >> 1
print("mid:",mid)
print("nums[mid]:",nums[mid])
root = TreeNode(nums[mid])
root.left = self.sortedArrayToBST(nums[start:mid])
root.right = self.sortedArrayToBST(nums[mid+1:end+1])
return root
110. 平衡二叉树
我的解法:
从底至顶(提前阻断法)
对二叉树做深度优先遍历DFS,递归过程中:
终止条件:当DFS越过叶子节点时,返回高度0;
返回值:
(1)从底至顶,返回以每个节点root为根节点的子树最大高度(左右子树中最大的高度值加1max(left,right) + 1);
(2)当我们发现有一例 左/右子树高度差 > 1 的情况时,代表此树不是平衡树,返回-1;
当发现不是平衡树时,后面的高度计算都没有意义了,因此一路返回-1,避免后续多余计算。
最差情况是对树做一遍完整DFS,时间复杂度为 O(N)。
# 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 isBalanced(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
return self.depth(root) != -1
def depth(self,root):
if not root: return 0
left = self.depth(root.left)
if left == -1: return -1
right = self.depth(root.right)
if right == -1: return -1
return max(left,right) + 1 if abs(left - right) < 2 else -1
111. 二叉树的最小深度
我的解法:
分治法:
判断左右两棵子树的最小深度,比较两个的最小值
注意:最小深度的定义是要到最近的叶子结点,所以如果一棵子树没有任何结点,那么最小值是另一棵子树的深度
故步骤:
1.日常判断当前结点是否为空,同时也是递归的终止条件
2.判断如果一棵子树没有任何结点,则最小值是另一棵子树的深度
3.若两棵子树都有结点,则最小值是两颗子树深度的最小值
# 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 minDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
if not root.left or not root.right:
return self.minDepth(root.left) + self.minDepth(root.right) + 1
return min(self.minDepth(root.left),self.minDepth(root.right)) + 1
112. 路径总和
我的解法:
遍历整棵树:如果当前节点不是叶子,对它的所有孩子节点,递归调用 hasPathSum 函数,其中 sum 值减去当前节点的权值;如果当前节点是叶子,检查 sum 值是否为 0,也就是是否找到了给定的目标和。
# 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 hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root:
return False
sum -= root.val
if not root.left and not root.right:
return (sum == 0)
return self.hasPathSum(root.left,sum) or self.hasPathSum(root.right,sum)