C++で二分木における指定された合計を持つルートからのパスをすべて出力する方法
この問題では、二分木とある合計値 S が与えられます。求めるのは、ルート(根)から木の任意のノードまで辿ったとき、経路上のノード値の合計が指定された値と一致するようなパスです。条件を満たすパスは複数存在する場合があるため、該当するすべてのパスを出力します。
入力例

Sum = 14 Output : path : 4 10 4 3 7
解法のアプローチ
この問題を解くには、二分木の先行順走査(プリオーダートラバーサル)を利用します。ルートから各ノードへ向かう途中で、それまでに通過したノード値の累積和(sum_so_far)を記録し、それが目的の合計と一致した時点で、そこまでのパスを出力します。
アルゴリズムの手順
- 現在のノードの値を累積和に加算し、パスに追加します。
- 累積和が指定された合計と一致したら、パスの内容を出力します。
- 左の子ノード・右の子ノードに対して、再帰的に同じ処理を繰り返します。
- 再帰から戻る際には、パスから現在のノードを取り除きます(バックトラッキング)。
C++での実装例
#include<bits/stdc++.h>
using namespace std;
struct Node{
int key;
struct Node *left, *right;
};
Node* insertNode(int key){
Node* temp = new Node;
temp->key = key;
temp->left = temp->right = NULL;
return (temp);
}
void printPathsUtilSum(Node* curr_node, int sum, int sum_so_far, vector<int> &path){
if (curr_node == NULL)
return;
sum_so_far += curr_node->key;
path.push_back(curr_node->key);
if (sum_so_far == sum ){
for (int i=0; i<path.size(); i++)
cout<<path[i]<<"\t";
cout<<endl;
}
if (curr_node->left != NULL)
printPathsUtilSum(curr_node->left, sum, sum_so_far, path);
if (curr_node->right != NULL)
printPathsUtilSum(curr_node->right, sum, sum_so_far, path);
path.pop_back();
}
void pathWithSum(Node *root, int sum){
vector<int> path;
printPathsUtilSum(root, sum, 0, path);
}
int main (){
Node *root = insertNode(4);
root->left = insertNode(10);
root->right = insertNode(3);
root->right->left = insertNode(7);
root->right->right = insertNode(1);
root->left->left = insertNode(8);
root->left->right = insertNode(6);
int sum = 14;
cout<<"Paths with the given sum are : "<<endl;
pathWithSum(root, sum);
return 0;
}
実行結果
合計が 14 となるパスは、次のように出力されます。
4 10 4 3 7
計算量について
時間計算量は O(n²) となります。これは、最悪の場合、各ノードで条件を満たしたパスの出力に最大 O(n) を要するためです。また、空間計算量は O(h)(h は木の高さ)で、再帰スタックおよびパスを保持するベクターによるものです。
-
C++で完全二分木の全ノードの合計を効率的に求める方法
問題の概要 正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。 今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。 例として、次のような木を考えてみましょう。 この木の場合、すべてのノードの合計は 30 になります。 解法のアプローチ この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から
-
C++で二分木の根から葉への最短経路を出力する方法|BFS(幅優先探索)による実装
問題の概要二分木が与えられたとき、根(ルート)から葉(リーフ)に至る複数の経路の中から、最も短い経路を見つけ出して出力するプログラムを作成します。木は左から右へと走査するため、同じ深さの最短経路が複数存在する場合は、左側にある最初に走査された最短経路を出力します。この問題は、キュー(queue)を使ったレベル順走査(幅優先探索・BFS)で各レベルを順にたどることで解くことができます。BFSは浅い階層から順に探索を進めるため、最初に見つかった葉への経路が、すなわち根から葉への最短経路となります。上図の二分木では、根から葉への経路として以下のものが考えられます。10 -> 3(すべての経路の