【C++】指定されたセグメント長から中点を含むセグメントを検索する方法
問題概要
この問題では、線分の長さを格納したサイズ m の配列 arr[] が与えられます。
線分は「0 から arr[0] まで」「arr[0] から arr[1] まで」というように順番に連結され、全体として1本の長い線を構成しています。求めたいのは、全線分の中間点が含まれるセグメントの番号です。
入出力例
入力
arr[] = {5, 7, 13}
出力
3
説明
線分 : (0, 5)、(5, 12)、(12, 25)
全体の長さは 25 なので、中点の座標は 12.5 になります。この中点は3番目のセグメント (12, 25) に含まれるため、答えは 3 となります。
解法アプローチ
まず、配列要素の合計値 arrSum を求め、中点の座標を arrSum / 2 として計算します。その上で、次のように判定を行います。
- 中点がいずれかの線分の始点または終点(境界)と一致する場合は -1 を返す。
- それ以外の場合は、中点を含むセグメント番号を返す。
具体的には、先頭から累積和を順に更新していき、累積和が初めて中点を超えた時点のインデックス +1 が答えになります。計算量は O(m)、必要な追加メモリは O(1) と非常に効率的です。
実装例(C++)
#include <iostream>
using namespace std;
// 中点を含むセグメント番号を返す関数
int findSegmentWithMidPoint(int n, int m, int segment_length[]) {
double centerPoint = (1.0 * n) / 2.0; // 全体の中点の座標
int sum = 0; // 累積和
int segment = -1; // 結果(該当なしの場合は -1)
for (int i = 0; i < m; i++) {
sum += segment_length[i];
// 中点が線分の境界と一致した場合
if ((double)sum == centerPoint) {
segment = -1;
break;
}
// 中点が現在のセグメント内にある場合
if (sum > centerPoint) {
segment = i + 1;
break;
}
}
return segment;
}
int main() {
int m = 3;
int segment_length[] = { 5, 7, 13 };
int arrSum = 0;
for (int i = 0; i < m; i++)
arrSum += segment_length[i]; // 全体の長さを計算
int ans = findSegmentWithMidPoint(arrSum, m, segment_length);
cout << "中点が含まれるセグメント番号は " << ans << " です";
return 0;
}
出力
中点が含まれるセグメント番号は 3 です
まとめ
本記事では、連結された線分の長さから全体の中点が属するセグメントを検索する方法を紹介しました。累積和を活用することで、時間計算量 O(m)・空間計算量 O(1) で効率的に求解できます。中点がちょうど線分の境界に一致するケース(-1 を返す条件)の扱いにも注意して実装しましょう。
-
C++で指定された頂点集合から到達可能なすべてのノードを検索する方法
無向グラフと頂点の集合が与えられたとき、その集合に含まれる各頂点から到達可能なすべてのノードを見つけることを考えます。 たとえば、次のようなグラフが入力として与えられた場合: 出力は [1,2,3] と [4,5] になります。これはグラフが2つの連結成分に分かれているためです。 解法のアプローチ この問題を解くためには、次の手順に従います。 nodes := グラフ内のノード数を取得する サイズが nodes+1 の訪問済み配列 visited を定義し、すべて 0 で初期化する 結果を格納するためのマップ m を定義する comp_sum := 0(連結成分のカウンタ) i := 0
-
C++で指定した開始文字から最長の連続パスの長さを求める方法
異なる文字が格納された行列(マトリックス)が与えられます。ある文字を起点として、現在の文字より1つ大きい連続した文字(例:a→b→c→d)をたどりながら、最長のパスの長さを見つけることが課題です。移動は、縦・横・斜めを含む8方向の隣接セルに対して可能です。 例えば、下図のような行列が与えられ、開始文字を「E」とします。 この行列で開始文字「e」から探索すると、最長の連続パスの長さは5となります。 アルゴリズムの考え方 最長パスを見つけるには、深さ優先探索(DFS)アルゴリズムを使用します。DFSの実行中には、同じ部分問題が何度も発生することがあります。このような部分問題を繰り返し計算しないよ