C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で二分木における指定された合計を持つルートからのパスをすべて出力する方法

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

入力例

C++で二分木における指定された合計を持つルートからのパスをすべて出力する方法

Sum = 14
Output : path : 4 10
4 3 7

解法のアプローチ

この問題を解くには、二分木の先行順走査(プリオーダートラバーサル)を利用します。ルートから各ノードへ向かう途中で、それまでに通過したノード値の累積和(sum_so_far)を記録し、それが目的の合計と一致した時点で、そこまでのパスを出力します。

アルゴリズムの手順

  1. 現在のノードの値を累積和に加算し、パスに追加します。
  2. 累積和が指定された合計と一致したら、パスの内容を出力します。
  3. 左の子ノード・右の子ノードに対して、再帰的に同じ処理を繰り返します。
  4. 再帰から戻る際には、パスから現在のノードを取り除きます(バックトラッキング)。

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 は木の高さ)で、再帰スタックおよびパスを保持するベクターによるものです。

  1. C++で完全二分木の全ノードの合計を効率的に求める方法

    問題の概要 正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。 今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。 例として、次のような木を考えてみましょう。 この木の場合、すべてのノードの合計は 30 になります。 解法のアプローチ この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から

  2. C++で二分木の根から葉への最短経路を出力する方法|BFS(幅優先探索)による実装

    問題の概要二分木が与えられたとき、根(ルート)から葉(リーフ)に至る複数の経路の中から、最も短い経路を見つけ出して出力するプログラムを作成します。木は左から右へと走査するため、同じ深さの最短経路が複数存在する場合は、左側にある最初に走査された最短経路を出力します。この問題は、キュー(queue)を使ったレベル順走査(幅優先探索・BFS)で各レベルを順にたどることで解くことができます。BFSは浅い階層から順に探索を進めるため、最初に見つかった葉への経路が、すなわち根から葉への最短経路となります。上図の二分木では、根から葉への経路として以下のものが考えられます。10 -> 3(すべての経路の