🖋

LeetCode 104. Maximum Depth of Binary Tree

に公開

はじめに

LeetCode 「104. Maximum Depth of Binary Tree」の問題をGoで解きました。

問題

https://leetcode.com/problems/maximum-depth-of-binary-tree/description

問題文

Given the root of a binary tree, return its maximum depth.

A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

和訳
二分木のルートが与えられたとき、その最大深度を返す。

二分木の最大深度は、ルート・ノードから最も遠いリーフ・ノードまでの最長経路に沿ったノードの数である。

         3       
      /     \    
     9      20   
            / \    
          15   7    
Input: root = [3,9,20,null,null,15,7]
Output: 3
Input: root = [1,null,2]
Output: 2

制約

  • The number of nodes in the tree is in the range [0, 104].
  • -100 <= Node.val <= 100

解答1:DFS(深さ優先探索、再帰)

二分木の最大深度を求める問題です。
まずDFSのアプローチで解きます。

左右の子の深さをそれぞれ求めて、大きい方+1(現在のノード分) を返すという方針です。
左右の子の深さは再帰的に求めます。
ルートから最も深いリーフノードまでの経路は、左右どちらかのサブツリー内にあります。
そのため、それぞれのサブツリーの最大深度を再帰的に求め、その大きい方に現在のノード分(+1)を加えることで全体の最大深度を求めることができます。

コード

func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }

    leftDepth := maxDepth(root.Left)
    rightDepth := maxDepth(root.Right)
    return max(leftDepth, rightDepth) + 1
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

例1だと以下の図のような流れで呼び出されます。

maxDepth(3)
 ├── maxDepth(9)
 │    ├── maxDepth(nil) → 0
 │    └── maxDepth(nil) → 0
 │    → max(0, 0) + 1 = 1
 └── maxDepth(20)
      ├── maxDepth(15)
      │    ├── maxDepth(nil) → 0
      │    └── maxDepth(nil) → 0
      │    → max(0, 0) + 1 = 1
      └── maxDepth(7)
           ├── maxDepth(nil) → 0
           └── maxDepth(nil) → 0
           → max(0, 0) + 1 = 1
      → max(1, 1) + 1 = 2
→ max(1, 2) + 1 = 3

計算量

  • 時間的計算量:O(n)
    • n はノード数(各ノードを1回ずつ訪れる)
  • 空間的計算量:O(h)
    • h は木の高さ(再帰呼び出しのスタックが木の高さ分使われる)

解答2:BFS(幅優先探索、Queue使用)

BFSでは Queue を使って木をレベル単位で探索します。
Queueに現在のレベルのノードを入れ、すべて処理したら1レベル進んだとみなして depth++ していきます。
Queue が空になったときの depth が最大深度になります。
BFSではレベルごとに進むため、「木の深さ」=「何回レベルを進んだか」をカウントすれば最大深度を求められます。

コード

func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }

    queue := []*TreeNode{root}
    depth := 0

    for len(queue) > 0 {
        levelSize := len(queue)

        for i := 0; i < levelSize; i++ {
            node := queue[0]
            queue = queue[1:] 

            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        depth++
    }
    return depth
}

例1だと以下の図のような流れとなります。

[3] → depth = 1
 ↓
[9, 20] → depth = 2
 ↓
[15, 7] → depth = 3
 ↓
[] → 終了 → 答え = 3

計算量

  • 時間的計算量:O(n)
    • n はノード数(各ノードを1回ずつ訪れる)
  • 空間的計算量:O(w)
    • w は木の最大幅(Queue に最大で一度に保持するノード数)

参考

二分木の問題は、以下の記事でも紹介していますので、参考にしてください。

GitHubで編集を提案

Discussion