C++で二分木の最下層・左端の値を求める方法
二分木が与えられたとき、その木の最も深い行(最下層)における左端の値を求める問題を考えてみましょう。例えば、次のような二分木があるとします。

この場合、最下層は [7, 4] であり、その中で最も左にある要素は 7 なので、出力は 7 となります。
解法のアプローチ
この問題は、深さ優先探索(DFS)を利用することでシンプルに解くことができます。ポイントは「必ず左側の子ノードから先に訪問する」ことです。こうすることで、それまでに到達した中で最も深いレベルへ最初に到達したノードが、自動的にそのレベルの左端のノードになります。
アルゴリズムの手順
- 最初に、答えを格納する
ansと、現在の最大レベルを記録するlvlという変数を用意します。 solve()というメソッドを定義します。このメソッドは木のノードとレベルを引数に取り、レベルの初期値は 0 です。動作は以下の通りです。- ノードが null の場合は何もせずに戻ります。
level > lvlの場合、ansにノードの値を代入し、lvlを現在のレベルで更新します。solve(ノードの左の子, level + 1)を呼び出します。solve(ノードの右の子, level + 1)を呼び出します。- メイン処理では、
lvl := -1と設定し、solve(root)を呼び出した後、ansを返します。
理解を深めるために、以下の実装を見てみましょう。
実装例
#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
cout << "[";
for(int i = 0; i<v.size(); i++){
cout << v[i] << ", ";
}
cout << "]"<<endl;
}
class TreeNode{
public:
int val;
TreeNode *left, *right;
TreeNode(int data){
val = data;
left = NULL;
right = NULL;
}
};
void insert(TreeNode **root, int val){
queue<TreeNode*> q;
q.push(*root);
while(q.size()){
TreeNode *temp = q.front();
q.pop();
if(!temp->left){
if(val != NULL)
temp->left = new TreeNode(val);
else
temp->left = new TreeNode(0);
return;
} else {
q.push(temp->left);
}
if(!temp->right){
if(val != NULL)
temp->right = new TreeNode(val);
else
temp->right = new TreeNode(0);
return;
} else {
q.push(temp->right);
}
}
}
TreeNode *make_tree(vector<int> v){
TreeNode *root = new TreeNode(v[0]);
for(int i = 1; i<v.size(); i++){
insert(&root, v[i]);
}
return root;
}
class Solution {
public:
int ans;
int lvl;
void solve(TreeNode* node, int level = 0){
if(!node || node->val == 0) return;
if(level > lvl){
ans = node->val;
lvl = level;
}
solve(node->left, level + 1);
solve(node->right, level + 1);
}
int findBottomLeftValue(TreeNode* root) {
lvl = -1;
solve(root);
return ans;
}
};
main(){
vector<int> v = {3,5,1,6,2,0,8,NULL,NULL,7,4};
TreeNode *tree = make_tree(v);
Solution ob;
cout <<(ob.findBottomLeftValue(tree));
}
入力
[3,5,1,6,2,0,8,null,null,7,4]
出力
7
計算量について
このアルゴリズムでは、各ノードを一度だけ訪問するため、時間計算量は O(n)(n はノード数)となります。また、再帰の深さは木の高さに依存するため、空間計算量は O(h)(h は木の高さ)です。最悪の場合、木が線形に偏っていると O(n) になりますが、バランスの取れた木であれば O(log n) に抑えられます。
-
C++で二分木の各階層における最大値を見つける方法
二分木が与えられたとき、その木の各階層(レベル)ごとの最大値を求めることを考えます。例えば、次のような二分木があるとします。この場合、出力は [1, 3, 9] となります。ルート(最上位)の階層には「1」だけが存在するため、最大値は 1第1階層には「3」と「2」があり、最大値は 3第2階層には「5」「3」「9」があり、最大値は 9解決のためのアプローチこの問題は、再帰的な深さ優先探索(DFS) を使うことで簡潔に解くことができます。手順は以下の通りです。結果を格納するための配列 ans を定義します。再帰関数 solve() を定義します。この関数はツリーノードとレベル(初期値は 0)を引数
-
C++の二分探索木(BST)で最小値のノードを見つける方法
二分探索木(Binary Search Tree、BST)が与えられたとき、その木の中から最小の要素を見つけることを考えます。例えば、以下のようなBSTがあるとします。この場合、最小要素は 1 になります。考え方二分探索木の重要な性質として、左部分木には必ず親ノードより小さい値が格納されるというものがあります。この性質を利用すると、次の手順で最小要素を見つけることができます。ルートノードから探索を開始します。現在のノードの左の子が NULL でない間、左の子へ移動を繰り返します。左の子が NULL になったノードの値が、木全体の中で最小の要素です。この操作の計算量は木の高さに依存し、平衡な二分