C++プログラム:二分木における最大独立集合(LIS)のサイズを求める方法
この記事では、与えられた二分木(バイナリツリー)における最大独立集合(LIS:Largest Independent Set)のサイズを求めるC++プログラムを紹介します。
独立集合とは、木の中で互いに隣接していない(親子関係にない)ノードだけで構成される集合のことです。つまり、「選んだノード同士が直接つながっていない」という条件のもとで、できるだけ多くのノードを選ぶ問題を解きます。
アルゴリズム
この問題は、動的計画法(メモ化再帰)を用いることで効率的に解けます。各ノードについて「そのノードを含まない場合」と「そのノードを含む場合」の2通りのサイズを計算し、大きい方を採用します。
開始。 構造体nを作成し、データd、左の子ポインタl、右の子ポインタrを宣言する。 2つの整数のうち大きい方を返す関数max()を定義する。 与えられた二分木における最大独立集合のサイズを返す関数LIS()を作成する。 現在のノードを含まない場合のサイズを計算する int size_excl = LIS(root->l) + LIS(root->r) 現在のノードを含む場合のサイズを計算する int size_incl = 1; if (root->l) size_incl += LIS(root->l->l) + LIS(root->l->r) if (root->r) size_incl += LIS(root->r->l) + LIS(root->r->r) 2つのサイズのうち大きい方を返す 新しいノードを生成する関数newnode()を作成する。 終了。
最適化のポイント
各ノードには計算済みのLIS値を格納するフィールドを持たせています。一度計算した結果はキャッシュとして再利用されるため、同じ部分木を繰り返し計算する無駄がなくなり、計算量が大幅に削減されます。
サンプルコード
#include <iostream>
using namespace std;
struct n {
int d;
int lis;
struct n *l, *r;
};
int max(int x, int y) {
return (x > y) ? x : y;
}
int LIS(struct n *root) {
if (root == NULL)
return 0;
if (root->lis)
return root->lis;
if (root->l == NULL && root->r == NULL)
return (root->lis = 1);
int lis_excl = LIS(root->l) + LIS(root->r);
int lis_incl = 1;
if (root->l)
lis_incl += LIS(root->l->l) + LIS(root->l->r);
if (root->r)
lis_incl += LIS(root->r->l) + LIS(root->r->r);
root->lis = max(lis_incl, lis_excl);
return root->lis;
}
struct n* newnode(int d) {
struct n* t = (struct n *) malloc(sizeof(struct n));
t->d = d;
t->l = t->r = NULL;
t->lis = 0;
return t;
}
int main() {
struct n *root = newnode(30);
root->l= newnode(20);
root->l->l = newnode(10);
root->l->r = newnode(7);
root->l->r->l = newnode(9);
root->l->r->r = newnode(6);
root->r = newnode(50);
root->r->r = newnode(26);
cout<<"Size of the Largest Independent Set is "<< LIS(root);
return 0;
}
実行結果
Size of the Largest Independent Set is 5
この例の二分木では、値が30・10・9・6・26である5つのノードを選ぶことで、互いに隣接しない最大の独立集合が得られます。
-
C++で完全二分木の全ノードの合計を効率的に求める方法
問題の概要 正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。 今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。 例として、次のような木を考えてみましょう。 この木の場合、すべてのノードの合計は 30 になります。 解法のアプローチ この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から
-
Pythonで二分木の中から最大のBST(二分探索木)の合計値を見つけるプログラム
問題の概要ある二分木が与えられたとします。この木の部分木の中に二分探索木(BST)が存在するかどうかを調べ、その中で最も大きなBSTを見つけ出し、そのノード値の合計を求めるのが目的です。合計値は、そのBSTに含まれる各ノードの値をすべて足し合わせたものになります。例えば、入力が次のような二分木だったとしましょう。この場合、出力は 12 となります。与えられた二分木の中に存在するBSTは次の部分木です。このBSTのノード値の合計 = 12 となります。解き方のアプローチこの問題を解くために、以下の手順で処理を進めます。変数 c := 0、m := null、value := 0 を初期化します。