C++でBST(二分探索木)の先行順巡回結果からルートより小さい要素の数を求める方法
この記事では、BST(二分探索木)の先行順巡回(プレオーダートラバーサル)の結果が与えられたときに、ルート(根)よりも小さい要素の個数を求める方法を解説します。
先行順巡回には「配列の最初の要素が必ずBSTのルートになる」という重要な性質があります。この性質を利用すれば、木を実際に構築しなくても効率的に答えを求められます。まずは具体例を見てみましょう。
問題の例
入力
preorder_result = [5, 4, 2, 1, 7, 6, 8, 9]
出力
3
ルートは配列の先頭にある「5」です。ルートより小さい要素は「4」「2」「1」の3つなので、答えは3になります。
アルゴリズム
先行順巡回の結果を配列として用意します。
配列の先頭要素(BSTのルート)を変数に保存します。
配列の2番目の要素から順にループで走査します。
各要素とルートを比較します。
現在の要素がルートより小さければ、カウントを1増やします。
最後にカウントを返します。
このアルゴリズムは配列を一度だけ走査するため、時間計算量はO(n)、追加のメモリはO(1)で済むという効率の良さが特徴です。
C++での実装
以下は、上記のアルゴリズムをC++で実装したコードです。
#include <bits/stdc++.h>
using namespace std;
int getElementsCount(int arr[], int n) {
if (n <= 0) {
return 0;
}
int root = arr[0], count = 0;
for (int i = 1; i < n; i++) {
if (arr[i] < root) {
count += 1;
}
}
return count;
}
int main() {
int preorder[] = {5, 4, 2, 1, 7, 6, 8, 9};
int n = 8;
cout << getElementsCount(preorder, n) << endl;
return 0;
}
実行結果
上記のコードを実行すると、次の出力が得られます。
3
まとめ
先行順巡回の「先頭要素がルートになる」という性質を利用すれば、BSTを構築することなく、ルートより小さい要素の数を線形時間O(n)で簡単に求められます。配列を一巡してルートと比較するだけなので、実装も非常にシンプルです。
-
C++で配列の全要素を削除するために必要な最小操作数を求める方法
問題の概要整数型の配列 arr が与えられたとき、配列のすべての要素を削除するために必要な最小の操作数を求めるのが課題です。ただし、要素を削除する際には次の制約が課されます。配列から任意の要素を自由に選択でき、その要素で割り切れるすべての要素を一度に配列から削除できる。例えば、arr[] = {2, 4, 15, 10, 8, 5, 3} の場合、すべての要素を削除するには3回の操作が必要です。2 を選択すると、{2, 4, 10, 8} が削除されます。5 を選択すると、{5, 15} が削除されます。3 を選択すると、{3} が削除されます。アルゴリズム配列を昇順にソートし、各要素の出現回
-
C++で配列内の数値の頻度(出現回数)を求める方法
配列に n 個の異なる要素が格納されているとします。この配列の中から、特定の要素が何回出現するか(頻度)を調べたい場合があります。例えば、配列 A = [5, 12, 26, 5, 3, 4, 15, 5, 8, 4] の中で「5」の頻度を調べると、答えは 3 になります。アルゴリズムの考え方この問題は、次の手順で解くことができます。1. 配列を左端から順に走査します。2. 現在の要素が調べたい数値と一致したら、カウンターを1つ増やします。3. 一致しない場合は、そのまま次の要素へ進みます。4. 配列の最後まで走査したら、カウンターの値が頻度となります。このアルゴリズムの計算量は O(n) で