前提・実現したいこと
プログラミング初心者です.
木構造の葉の最小の深さを再帰プログラミングを用いて求めようとしています。
例えば、以下の木構造では最小の深さはB:8の1となります。
A: 2 │ ├──B: 8 │ └──C: 5 │ ├──D: 11 │ │ │ └──F: 5 │ └──E: 6
発生している問題・エラーメッセージ
ところが、現状のコードでは最小の深さが5である以下の木構造でも出力が1となってしまいます。
自力では長時間考えても糸口が掴めませんでした。どなたか解決策を教えていただけますでしょうか。
A: 1 │ └──A: 2 │ └──E: 3 │ └──A: 4 │ └──I: 5 │ └──A: 6
現状のソースコード
Python
1def min_depth_func(tree): #treeは木構造のインスタンス、引数はtreeのみ 2 if tree.num_children() == 0: 3 print("base route") 4 return 1 5 6 num_depth = 0 7 depth_lst = [] 8 for kid in tree.children: 9 num_depth += min_depth_func(kid) 10 depth_lst.append(num_depth) 11 min_depth = min(depth_lst) 12 return min_depth
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
考え方の参考として、コード例を挙げておきます。考え方を示すことが目的なので、この回答ではツリーが以下のようなJSONで与えられ、これをパースして得られるdictを処理対象のツリーとします。
json
1{ 2 "id":1, 3 "children":[ 4 { 5 "id":8 6 }, 7 { 8 "id":5, 9 "children":[ 10 { 11 "id":11, 12 "children":[ 13 { 14 "id":55 15 } 16 ] 17 }, 18 { 19 "id":6 20 } 21 ] 22 } 23 ] 24}
上記のJSONをパースして出来るdicttree
を引数として与え、最も浅いところの葉のdepth
と、そのdepth
の深さにある(複数存在する可能性のある)葉の中で最初にみつけたもののid
を持つdict
(たとえば、 {'id': 8, 'depth': 1}
)
を返す関数として、min_depth_func(tree)
を作成しました。
Python3
1def min_depth_func(tree): 2 min_depth_node = {'id': -1, 'depth': None} 3 4 def update_min_depth_node_recursively(node, depth=0): 5 nonlocal min_depth_node 6 7 min_depth = min_depth_node['depth'] 8 if 'children' not in node: 9 if min_depth is None or depth < min_depth: 10 min_depth_node = {'id': node['id'], 'depth': depth} 11 else: 12 if min_depth is None or depth + 1 <= min_depth: 13 for child in node['children']: 14 update_min_depth_node_recursively(child, depth + 1) 15 16 update_min_depth_node_recursively(tree) 17 18 return min_depth_node 19
子ノードを左から調べていき、min_depth_node
を更新します。最も浅い葉を特定するのが目的なので、min_depth_node['depth']
より深い位置へは降りていかないようにしています。
以下は、5個のテストツリーで、上記のmin_depth_func(tree)
を試すコードです。
Python3
1if __name__ == '__main__': 2 import json 3 4 # test_1: min_width=1 (id: 8) 5 test_1 = '''{ 6 "id":1, 7 "children":[ 8 { 9 "id":8 10 }, 11 { 12 "id":5, 13 "children":[ 14 { 15 "id":11, 16 "children":[ 17 { 18 "id":55 19 } 20 ] 21 }, 22 { 23 "id":6 24 } 25 ] 26 } 27 ] 28 }''' 29 30 # test_2: min_width=1 (id: 8) 31 test_2 = '''{ 32 "id":1, 33 "children":[ 34 { 35 "id":5, 36 "children":[ 37 { 38 "id":11, 39 "children":[ 40 { 41 "id":55 42 } 43 ] 44 }, 45 { 46 "id":6 47 } 48 ] 49 }, 50 { 51 "id":8 52 } 53 ] 54 }''' 55 56 # test_3: min_width=0 (id: 1) 57 test_3 = '''{ 58 "id":1 59 }''' 60 61 # test_4: min_width=2 (id: 5) 62 test_4 = '''{ 63 "id":1, 64 "children": [ 65 { "id": 2, "children": [ { "id": 5 } ] }, 66 { "id": 3, "children": [ { "id": 6 } ] }, 67 { "id": 4, "children": [ { "id": 7 } ] } 68 ] 69 }''' 70 71 # test_5: min_width=1 (id: 8) 72 test_5 = '''{ 73 "id":1, 74 "children": [ 75 { "id": 2, "children": [ { "id": 5 } ] }, 76 { "id": 3, "children": [ { "id": 6 } ] }, 77 { "id": 4, "children": [ { "id": 7 } ] }, 78 { "id": 8 } 79 ] 80 }''' 81 82 for i, test_json in enumerate([test_1, test_2, test_3, test_4, test_5]): 83 tree_root = json.loads(test_json) 84 result = min_depth_func(tree_root) 85 print(f'test_{i+1}: min_depth_node={result}') 86
出力結果:
test_1: min_depth_node={'id': 8, 'depth': 1}
test_2: min_depth_node={'id': 8, 'depth': 1}
test_3: min_depth_node={'id': 1, 'depth': 0}
test_4: min_depth_node={'id': 5, 'depth': 2}
test_5: min_depth_node={'id': 8, 'depth': 1}
**動作確認用サンプル: ** ???? tera: 371423@replit.com/@kilesa
備考: ツリーのノードがどのようなデータ構造であるせよ、再帰による探索中に、不必要に深いところまで調べないで済むようなロジックを入れられるといいですね。
投稿2021/11/29 07:08
編集2021/11/29 07:56退会済みユーザー
総合スコア0
0
ベストアンサー
以下のような感じでどうでしょうか?
python
1class Tree: 2 def __init__(self, val): 3 self.val = val 4 self.children = [] 5 6 def num_children(self): 7 return len(self.children) 8 9 10def min_depth_func(tree): 11 if tree.num_children() == 0: 12 return 1 13 14 depth_lst = [] 15 for kid in tree.children: 16 depth_lst.append(min_depth_func(kid)) 17 return 1 + min(depth_lst) 18 19 20A = Tree(1) 21B = Tree(8) 22C = Tree(5) 23D = Tree(11) 24E = Tree(6) 25F = Tree(5) 26A.children.append(B) 27A.children.append(C) 28C.children.append(D) 29C.children.append(E) 30D.children.append(F) 31ans = min_depth_func(A) - 1 # 根は0としてカウントするようなので、-1する 32print(ans) 33 34A = Tree(1) 35B = Tree(2) 36C = Tree(3) 37D = Tree(4) 38E = Tree(5) 39F = Tree(6) 40A.children.append(B) 41B.children.append(C) 42C.children.append(D) 43D.children.append(E) 44E.children.append(F) 45ans = min_depth_func(A) - 1 46print(ans)
投稿2021/11/29 06:06
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
全体的にうまくコード化できていません。
以下の概念コードを参考にしてみてください。
Python
1def min_depth_func(tree, 現在の階層位置): 2 if tree.num_children() == 0: 3 return 現在の階層位置 4 5 for kid in tree.children: 6 子供の結果 = min_depth_func(kid, 現在の階層位置+1) 7 8 return min(子供たちの結果)
投稿2021/11/29 02:48
総合スコア38341
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/29 03:47
2021/11/29 04:03
2021/11/29 13:47
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/29 13:43