検索ガイド -Search Guide-

単語と単語を空白で区切ることで AND 検索になります。
例: python デコレータ ('python' と 'デコレータ' 両方を含む記事を検索します)
単語の前に '-' を付けることで NOT 検索になります。
例: python -デコレータ ('python' は含むが 'デコレータ' は含まない記事を検索します)
" (ダブルクオート) で語句を囲むことで 完全一致検索になります。
例: "python data" 実装 ('python data' と '実装' 両方を含む記事を検索します。'python data 実装' の検索とは異なります。)
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
>>
python_coding_challenge

Python coding challenge - [Depth First Search (DFS) for Graph and Tree] パスを構成するノードの value の合計値が target と同じものを見つけよう! 投稿一覧へ戻る

Published 2022年9月3日9:58 by mootaro23

SUPPORT UKRAINE

- Your indifference to the act of cruelty can thrive rogue nations like Russia -

Python Coding Challenge - How will you find the path sum in a binary tree?
(Python コーディングチャレンジ [パスを構成するノードの value の合計値が target と同じものを見つけよう!] 編)

この問題も DFS アルゴリズムを利用する問題のバリエーションの1つです。ルートノードから全てのリーフノードに至る path を列挙し、それぞれの path を構成するノードの value 値の合計をキープ、比較するものです。
問題:
バイナリツリーが渡されます。このバイナリツリーを構成する各ノードの value は int 値です。この時、ルートノードからリーフノードに至る paths の中に、その path を構成するノードの value の合計値が与えられる target と等しいものがあるか否かを返すプログラムを記述してください。合計値が target と等しいものが含まれる場合は True、含まれない場合は False を返します。
例:
下図のバイナリツリーと target として 22 が渡されたとします:
figure_5_5_example
(例) 渡されるバイナリツリー
- Shyamkant Limaye (2021). Python Quick Interview Guide. BPB Publications -
与えられる引数: root, 22

# 出力: True
例の解説:
与えられたバイナリツリーに含まれるパス 5-4-11-2 の合計値は 22 であり、指定された target と同じです。よって True を返します。
また関数定義は以下のような形です (同じである必要はありません):
from typing import Optional

def has_path_sum(root: Optional[TreeNode], sum: int) -> bool:
...
また TreeNode クラスは「Python coding challenge の前準備: Basics of Graph Theory Part.3 - Representation and Manipulation of Trees (グラフ理論の基礎総復習 その3 - ツリーの表現と操作)」で定義した次のクラスを利用します:
from typing import Optional, Any


class TreeNode:
def __init__(self, v: Any):
self.val = v
self.left: Optional[TreeNode] = None
self.right: Optional[TreeNode] = None
作成したプログラムは以下のテストをパスする必要があります:
import unittest


def make_tree(arr: list[Optional[int]], root: Optional[TreeNode] = None, index: int = 0) -> Optional[TreeNode]:
if index < len(arr):
root = TreeNode(arr[index])
root.left = make_tree(arr, root.left, index * 2 + 1)
root.right = make_tree(arr, root.right, index * 2 + 2)
return root


class TestHasPathSum(unittest.TestCase):

def setUp(self):
arr = [5, 4, 8, 11, None, 13, 4, 7, 2, None, None, None, 1, None, None]
self.root = make_tree(arr)

def test_1(self):
res = has_path_sum(self.root, 27)
self.assertTrue(res)

def test_2(self):
res = has_path_sum(self.root, 22)
self.assertTrue(res)

def test_3(self):
res = has_path_sum(self.root, 11)
self.assertFalse(res)

def test_4(self):
res = has_path_sum(self.root, 17)
self.assertTrue(res)
考え方:
この問題の解決にも再帰処理を利用します。あるパスを構成するノードの合計は以下のような再帰計算によって求めることになります:
path を構成するノードの合計値 = 現在のノードの値 + それ以下の子ノードの合計値
またこの再帰処理の base case は leaf node (パスの末端に位置するノード) に到達した場合です。
こうした再帰操作を行うためのヘルパー関数として has_sum(root, sum, cur) を定義します。この関数では has_path_sum() が受け取る引数に加えて、ルートノードから現在の階層までのノードの合計値をセットしておく cur 引数も受け取るようにします。この cur の値に今回の再帰処理の対象となるノードの値を加えた時点で、合計値がターゲットである sum と等しいかを比較し、等しく、かつ、このノードが leaf node (つまり left と right の子ノードがともに None) であれば True を返します。
しかしいずれかの条件が満たされていない場合は leaf node に達するまで同じ処理を繰り返すことになります:
プログラム実装例:
from typing import Optional

def has_path_sum(root: Optional[TreeNode], sum: int) -> bool:
def has_sum(root: Optional[TreeNode], sum: int, cur: int) -> bool:
if root is None:
return False

rv = 0 if root.val is None else root.val
cur += rv
if cur == sum and root.left is None and root.right is None:
return True
return has_sum(root.left, sum, cur) or has_sum(root.right, sum, cur)

return has_sum(root, sum, 0)
Complexity Analysis
(アルゴリズム解析)
Time complexity (実行計算時間):
渡されたバイナリツリーを1度だけ走査していますから O(n) です。
Space complexity (実行メモリ要求量):
再帰呼び出しの回数は渡されたバイナリツリーの「高さ (h)」に依存します。またノード数が n のバイナリツリーの最大高さは n ですから O(n) です。