二分木の単純なアルゴリズムの迅速な実装

1.二分木を構築する

public class TreeNode {
    public var val: Int
    public var left: TreeNode?
    public var right: TreeNode?
    public init(_ val: Int=0, _ left: TreeNode?=nil, _ right: TreeNode?=nil) {
      self.val = val
      self.left = left
      self.right = right
    }
}
复制代码

2.二分木をトラバースします

2.1。プレオーダートラバーサル(ルート-左-右)

func preorderTraversal ( _ root: TreeNode?) -> [Int] {
    var r : [Int] = []
    if(root?.val == nil) {
        return []
    } else {
        r.append(root!.val)
        r.append(contentsOf: preorderTraversal(root!.left))
        r.append(contentsOf: preorderTraversal(root!.right))
        return r
    }
}
复制代码

2.2。順序のないトラバーサル(左-ルート-右)

func middenTraversal ( _ root: TreeNode?) -> [Int] {
    var r : [Int] = []
    if(root?.val == nil) {
        return []
    } else {
        r.append(contentsOf: middenTraversal(root?.left))
        r.append(root!.val)
        r.append(contentsOf: middenTraversal(root?.right))
        return r
    }
}
复制代码

2.3。ポストオーダートラバーサル(左右ルート)

func postorderTraversal ( _ root: TreeNode?) -> [Int] {
    var r : [Int] = []
    if(root?.val == nil) {
        return []
    } else {
        r.append(contentsOf: postorderTraversal(root?.left))
        r.append(contentsOf: postorderTraversal(root?.right))
        r.append(root!.val)
        return r
    }
}
复制代码

2.4.レイヤー順序トラバーサル(レイヤーごとのルートノードトラバーサル)

func levelOrder ( _ root: TreeNode?) -> [[Int]] {
    // write code here
    var res = [[Int]]()
    if root == nil {
        return res
    }
    var queue = [root!] //定义一个TreeNode队列,后续就操作这个队列
    while !queue.isEmpty { 
      //TreeNode不为空就遍历,queue中先有一个TreeNode就是root,第2次就两个,第3次4个,依次类推,同时res中一层层地输出
        let r = getNodes(queue)
        res.append(r.vals)
        queue = r.nodes
    }
    return res
}

//得到每一层的val和下一层的node
func getNodes(_ nodes:[TreeNode]) -> (vals: [Int], nodes: [TreeNode]) {
    var values = [Int]()
    var nextNodes = [TreeNode]()
    for treeNode in nodes {
        values.append(treeNode.val)
        if let l = treeNode.left {
            nextNodes.append(l)
        }
        if let r = treeNode.right {
            nextNodes.append(r)
        }
    }
    return (values, nextNodes)
}
复制代码

二叉树的遍历的顺序是相对于根结点来说的,根在前就是前序,根在中为中序,根在后为后序

3.二分木の特性の判断

3.1。二分木の最大の深さを見つける

深さは、ツリーのルートノードから任意のリーフノードまでのパス上のノードの数を指し、最大深さはすべてのリーフノードの最大深さです。

func maxDepth ( _ root: TreeNode?) -> Int {
    // write code here
    if(root?.val == nil) {
        return 0
    }
    return 1 + max(maxDepth(root?.left),maxDepth(root?.right))
}
复制代码

3.2.二分木のパス合計に特定の値があるかどうか

二分木ルートと値の合計が与えられた場合、ルートノードからリーフノードまでのノード値の合計が合計に等しいかどうかを判断します

左右のサブツリーにsum-root.val値があるかどうかを単純化してから、再帰的に解決します

func hasPathSum ( _ root: TreeNode?,  _ sum: Int) -> Bool {
    // write code here
    if root == nil {
        return false
    }
    if root?.left == nil && root?.right == nil && sum - root!.val == 0 {
        return true
    }
    return hasPathSum(root?.left, sum-root!.val) || hasPathSum(root?.right, sum-root!.val)
}
复制代码

3.3.二分木は対称ですか?

つまり、左右のサブツリーが対称であるかどうか

func isSymmetrical ( _ pRoot: TreeNode?) -> Bool {
    // write code here
    if pRoot == nil {
        return true
    }
    return isSame(pRoot?.left, pRoot?.right)
}

func isSame(_ leftTreeNode: TreeNode?, _ rightTreeNode: TreeNode?) -> Bool {
    if leftTreeNode == nil && rightTreeNode == nil {
        return true
    }
    if leftTreeNode == nil || rightTreeNode == nil {
        return false
    }
    return leftTreeNode?.val == rightTreeNode?.val && isSame(leftTreeNode?.left, rightTreeNode?.right) && isSame(leftTreeNode?.right, rightTreeNode?.left)
}
复制代码

3.4、二分木をマージする

2つのバイナリツリーをマージします。既存のノードがある場合は、ノード値を追加します。そうでない場合、空の位置は別のツリーのノードに置き換えられます。

func mergeTrees ( _ t1: TreeNode?,  _ t2: TreeNode?) -> TreeNode? {
    // write code here
    if t1 == nil {
        return t2
    }
    if t2 == nil {
        return t1
    }
    return TreeNode(t1!.val+t2!.val, mergeTrees(t1?.left, t2?.left), mergeTrees(t1?.right, t2?.right))
}
复制代码

3.5、二分木の鏡像

指定されたバイナリツリーを操作し、ソースバイナリツリーのミラーイメージに変換します。

func Mirror ( _ pRoot: TreeNode?) -> TreeNode? {
    // write code here
    if pRoot == nil {
        return nil
    }
    return TreeNode(pRoot!.val, Mirror(pRoot?.right), Mirror(pRoot?.left))
}
复制代码

4.まとめ

  1. 二分木の問題は、一般的に、最初に空を考慮し、次にルートノードを処理し、次に左右のサブツリーを処理します。
  2. 左と右のサブツリーはそれぞれ二分木であるため、二分木の問題は一般的に再帰によって処理されます
  3. 二分木の問題の再帰
  4. 再帰
  5. 再帰
  6. 再帰

おすすめ

転載: juejin.im/post/7080413988667785230
おすすめ