- 二叉树(12道):
- 剑指Offer(07):重建二叉树
- 剑指Offer(26):树的子结构
- 剑指Offer(27):二叉树的镜像
- 剑指Offer(28):对称的二叉树
- 剑指Offer(32):从上往下打印二叉树
- 剑指Offer(32):分行从上到下打印二叉树
- 剑指Offer(32):之字形打印二叉树
- 剑指Offer(34):二叉树中和为某一值的路径
- 剑指Offer(37):序列化二叉树
- 剑指Offer(55):二叉树的深度
- 剑指Offer(55):平衡二叉树
- 剑指Offer(五十七):二叉树的下一个结点(未找到该题目)
- 二叉搜索树(3道):
- 剑指Offer(33):二叉搜索树的后序遍历序列
- 剑指Offer(36):二叉搜索树与双向链表
- 剑指Offer(54):二叉搜索树的第k大节点
面试题7:重建二叉树
题目一
思路一
代码
class Solution {
func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? {
if preorder.count == 0 || inorder.count == 0 {
return nil
}
//构建二叉树根结点
let root: TreeNode? = TreeNode.init(preorder[0])
//对中序序列进行遍历
for (index, num) in inorder.enumerated() {
// 如果找到根节点
if num == preorder[0] {
root?.left = buildTree(
Array(preorder[1..<index+1]),
Array(inorder[0..<index])
)
root?.right = buildTree(
Array(preorder[index+1..<preorder.endIndex]),
Array(inorder[index+1..<inorder.endIndex])
)
}
}
return root
}
}
面试题26:树的子结构
题目一
思路一
代码
class Solution {
func isSubStructure(_ A: TreeNode?, _ B: TreeNode?) -> Bool {
if A == nil || B == nil {
return false
}
return dfs(A,B) || isSubStructure(A?.left,B) || isSubStructure(A?.right, B)
}
func dfs(_ A: TreeNode?, _ B: TreeNode?) -> Bool {
if B == nil {
return true
}
if A == nil || A!.val != B!.val {
return false
}
return dfs(A?.left, B?.left) && dfs(A?.right, B?.right)
}
}
面试题27:二叉树的镜像
## 题目一
思路一
代码
func mirrorTree(_ root: TreeNode?) -> TreeNode? {
guard let root = root else { return nil }
let right = mirrorTree(root.right)
let left = mirrorTree(root.left)
root.right = left
root.left = right
return root
}
func mirrorTree2(_ root: TreeNode?) -> TreeNode? {
guard root != nil else {
return nil
}
var queue = [TreeNode]()
queue.append(root!)
while !queue.isEmpty {
let node = queue.removeFirst()
let nodeLeft = node.left
node.left = node.right
node.right = nodeLeft
if node.left != nil {
queue.append(node.left!)
}
if node.right != nil {
queue.append(node.right!)
}
}
return root
}
面试题28:对称的二叉树
题目一
思路一
代码
func isSymmetric(_ root: TreeNode?) -> Bool {
guard let root = root else { return true }
return dfs(left: root.left, right: root.right)
}
func dfs(left: TreeNode?, right: TreeNode?) -> Bool {
if left == nil && right == nil {
return true
}
if left == nil || right == nil {
return false
}
if left!.val != right!.val {
return false
}
return dfs(left: left!.left, right: right!.right) && dfs(left: left!.right, right: right!.left)
}
面试题32:从上往下打印二叉树
题目一
思路一
代码
class Solution {
func levelOrder(_ root: TreeNode?) -> [Int] {
var stack = [Int]()
if let root = root {
var nodes = [root]
var idx = 0
while idx < nodes.count {
let node = nodes[idx]
stack.append(node.val)
if let left = node.left {
nodes.append(left)
}
if let right = node.right {
nodes.append(right)
}
idx += 1
}
}
return stack
}
}
题目二:分行从上到下打印二叉树
代码
func levelOrder(_ root: TreeNode?) -> [[Int]] {
guard let root = root else { return [] }
var result = [[Int]]()
var queue: [TreeNode] = [root]
while !queue.isEmpty {
var current = [Int]()
for _ in 0 ..< queue.count {
let node = queue.removeFirst()
current.append(node.val)
if node.left != nil {
queue.append(node.left!)
}
if node.right != nil {
queue.append(node.right!)
}
}
result.append(current)
}
return result
}
题目三:之字形打印二叉树
思路一
代码
func zigzagLevelOrder(_ root: TreeNode?) -> [[Int]] {
//1. 空判断
guard let root = root else { return [[Int]]() }
var result = [[Int]]()
var queue = [root]
var isZ = false
//2. 创建队列,加入root
while !queue.isEmpty {
var cur = [Int]()
//3. 遍历一次队列
for _ in 0..<queue.count {
let node = queue.removeFirst()
//4. 将队列的值保存
cur.append(node.val)
//5. 队列中添加新值
if node.left != nil {queue.append(node.left!)}
if node.right != nil {queue.append(node.right!)}
}
if isZ { cur.reverse() }
result.append(cur)
isZ = !isZ
}
return result
}
面试题34:二叉树中和为某一值的路径
题目一
思路一
代码
var path = [Int]()
var res = [[Int]]()
func pathSum(_ root: TreeNode?, _ sum: Int) -> [[Int]] {
dfs(root, sum)
return res
}
func dfs(_ root: TreeNode?, _ sum: Int) {
guard let root = root else { return }
path.append(root.val)
let tmp = sum - root.val
if tmp == 0 && root.left == nil && root.right == nil {
res.append(path)
}
dfs(root.left, tmp)
dfs(root.right, tmp)
path.removeLast() // 重点,遍历完后,需要把当前节点remove出去,因为用的是同一个list对象来存所有的路径
}
面试题37:序列化二叉树
题目一
略
面试题55:二叉树的深度
题目一
思路一
代码
func maxDepth(_ root: TreeNode?) -> Int {
guard let root = root else { return 0 }
let leftDepth = maxDepth(root.left)
let rightDepth = maxDepth(root.right)
return max(leftDepth, rightDepth) + 1
}
题目二:平衡二叉树
思路一
代码
class Solution {
//! 是否是平衡树
func isBalanced(_ root: TreeNode?) -> Bool {
if root == nil {
return true
}
return help(root) >= 0
}
func help(_ root:TreeNode?) ->Int {
if root==nil {
return 0
}
let leftHeight = help(root?.left)
let rightHeight = help(root?.right)
//! 提前退出
if leftHeight == -1 || rightHeight == -1 || abs(leftHeight-rightHeight) > 1 {
return -1
} else {
return max(leftHeight, rightHeight)+1
}
}
}
面试题33:二叉搜索树的后序遍历序列
题目一
思路一
代码
class Solution {
func verifyPostorder(_ postorder: [Int]) -> Bool {
return recur(postorder)
}
func recur(_ postorder: [Int]) -> Bool {
if postorder.count == 1 || postorder.count == 0 { //这里,当只有一个节点或者无节点,认为是。
return true
}
var i = 0
let length = postorder.count
let root = postorder.last!
for num in postorder[0..<length - 1] { //注意剔除最后一个元素,即根节点。
if num > root {
break
}
i += 1
}
if i < length - 1 {
for num in postorder[i..<length - 1] { //查看右半部分节点是否满足条件。
if num < root {
return false
}
}
}
var left = true
if i > 0 {
left = self.recur(Array(postorder[0..<i])) //递归左边的子树,看看是否满足条件。
}
var right = true
if i < length - 1 {
right = verifyPostorder(Array(postorder[i..<length - 1])) //递归右边的子树,看是否满足条件。
}
return left && right
}
}
面试题36:二叉搜索树与双向链表
题目一
思路一
面试题54:二叉搜索树的第k大节点
题目一
思路一
代码
class Solution {
func kthLargest(_ root: TreeNode?, _ k: Int) -> Int {
var stack = [TreeNode?]() //模拟栈,临时存储待探索的节点
var curr: TreeNode? = root //指向树根
var nodeVals = [Int]() //存储各个节点的值
//中序遍历二叉树
while curr != nil || !stack.isEmpty {
while curr != nil {
stack.append(curr)
curr = curr?.left
}
curr = stack.removeLast()
nodeVals.append(curr!.val) //将每个节点值加入到数组中。因为是二叉搜索树,所以中序遍历的结果是递增的结果
curr = curr?.right
}
return nodeVals[nodeVals.count - k]
}
}