C++でバイナリ配列内の0を1に置き換えて最長の連続する1のシーケンスを取得する方法
N個の要素からなる配列を考えます。各要素は0または1のいずれかです。この中から1つの0を1に置き換えることで、最も長い連続した1のシーケンスを得られる位置を見つけるのが本記事のテーマです。
例えば、配列が arr = [1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1] の場合、答えとなるインデックスは9です。インデックス9の0を1に置き換えることで、最大の連続する1のシーケンスが実現します。
アルゴリズムの考え方
この問題を効率的に解くには、次の3つのインデックスを追跡する必要があります。
- 現在のインデックス(curr)
- 直前の0のインデックス(pz)
- 前々回の0のインデックス(ppz)
配列を先頭から走査し、要素が0であるときに curr と ppz の差を計算します。この差が現在の最大値(count_max)より大きければ、最大値を更新します。走査が終わったら、最大の差に対応するpz(直前の0のインデックス)を返します。この手法により、時間計算量O(n)・空間計算量O(1)で問題を解くことができます。
サンプルコード
#include<iostream>
using namespace std;
int findIndex(bool arr[], int n) {
int count_max = 0;
int index;
int pz = -1;
int ppz = -1;
for (int curr=0; curr<n; curr++) {
if (arr[curr] == 0) {
if (curr - ppz > count_max){
count_max = curr - ppz;
index = pz;
}
ppz = pz;
pz = curr;
}
}
if (n-ppz > count_max)
index = pz;
return index;
}
int main() {
bool arr[] = {1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "Index of 0 to be replaced is "<< findIndex(arr, n);
}実行結果
Index of 0 to be replaced is 9
このコードでは、0が出現するたびに「前々回の0」と「現在の位置」の間隔を確認し、これまでの最大値と比較しています。こうすることで、任意の0を1に置き換えた場合に得られる最長の連続シーケンスを常に把握でき、最適な置き換え位置を特定できます。
-
【C++】二分木における最長連続シーケンス経路の求め方を解説
問題の概要二分木が与えられたとき、最長の連続シーケンス経路の長さを求める問題を考えます。ここで「経路」とは、ある開始ノードから親子のつながり(親から子へのエッジ)に沿って、木の中の任意のノードまでをたどるノードの列を指します。最長の連続経路は必ず親から子の方向へ進む必要があり、逆方向(子から親)へさかのぼることは認められません。たとえば、次のような二分木が入力として与えられた場合を考えてみましょう。この場合、最長の連続シーケンス経路は 3 → 4 → 5 となるため、出力は 3 になります。アルゴリズムのアプローチこの問題は、木を深さ優先探索(DFS)でたどりながら、連続する値の並びを追跡する
-
C++で配列を実装した二分木
二分木は、ツリーの各ノードが最大2つの子ノードを持つことができる特殊なタイプのツリーです。これらの子ノードは、右子および左子と呼ばれます。 単純な二分木は-です 木を表現するには、2つの方法があります。 リンクリストを使用する動的ノード表現 配列を使用する順次表現。 ここでは、二分木の配列表現について説明します。このために、BTのノードに番号を付ける必要があります。この番号付けは、0から(n-1)または1からnまで開始できます。 配列内のノードとその親ノードおよび子ノードの位置を導き出します。 0インデックスベースのシーケンスを使用する場合 親ノードがインデックスpであ