C++で厳密に増加するサブ配列を数える方法を解説
整数要素を含む配列が与えられたとき、その配列から取り出せるすべてのサブ配列(部分配列)の中で、「厳密に増加している」(すべての要素が直前の要素より大きい)ものの個数を求めるのがこの問題の目的です。条件を満たさないサブ配列は候補から除外します。
ここでのポイントは、サブ配列の先頭2つの要素(0番目と1番目)の時点ですでに増加していない場合、それ以降のチェックを打ち切ることで無駄な計算を省くという効率的なアプローチです。
C++での例
入力: int a[] = {1, 7, 5}
出力: 厳密に増加するサブ配列の数は 1
説明: 考えられるサブ配列は {1,7,5}、{1,7}、{7,5} の3つですが、このうち厳密に増加しているのは {1,7} のみです。
入力: int a[] = {1, 2, 7, 10}
出力: 厳密に増加するサブ配列の数は 6
説明: {1,2}、{1,2,7}、{1,2,7,10}、{2,7}、{2,7,10}、{7,10} の6つすべてが厳密に増加しているため、答えは6になります。
プログラムで使用するアプローチ
- 配列を宣言し、要素を入力した後、そのデータと配列の長さを関数 countIncSubarrays(a, n) に渡して処理を行います。
- 関数内では、まずカウント用の変数を0で初期化します。
- 外側のループで i を 0 から配列の長さまで回します。
- 内側のループで j を i+1 から配列の長さまで回します。
- a[j] が a[j-1] より大きければ count をインクリメントし、そうでなければ break でループを抜けます(増加順序のチェックが失敗したため)。
- main 関数側で関数の戻り値を受け取り、結果として出力します。
C++コード例
#include <iostream>
using namespace std;
int countIncSubarrays(int a[], int n) {
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (a[j] > a[j - 1])
count++;
else
break;
}
}
return count;
}
int main() {
int a[] = {1, 2, 7, 10};
int n = sizeof(a) / sizeof(a[0]);
int result = countIncSubarrays(a, n);
cout << "厳密に増加するサブ配列の数は " << result << endl;
return 0;
}
上記のコードを実行すると、次の出力が得られます。
出力
厳密に増加するサブ配列の数は 6
計算量について
このアルゴリズムの最悪計算量は O(n²) です。ただし、増加が途切れた時点で内側のループを即座に抜けるため、実際の実行時間は入力データの性質(増加区間の長さ)によって大きく短縮されます。単純で理解しやすい実装であり、小〜中規模の配列に対しては十分に実用的な手法です。
-
C++で平面内に形成できる平行四辺形の数を数えるアルゴリズム
本記事の課題は、平面上に与えられた点集合から形成できる平行四辺形の個数を求めることです。平行四辺形とは、四角形の対辺が互いに平行であり、それに伴って対角も等しくなる四角形のことを指します。 入力 − int a[] = {0, 2, 5, 5, 2, 5, 2, 5, 2} int b[] = {0, 0, 1, 4, 3, 8, 7, 11, 10} 出力 − 平面内の平行四辺形の数 − 3 説明 − (x, y) 座標の点が与えられており、これらの点を組み合わせると、図のように 3 つの平行四辺形を形成できます。 入力 − a[] = {0, 3, 1, 4, 1, 5} b[] =
-
C++で配列内の反転数(Inversion Count)を求めるプログラムの解説
「反転数(Inversion Count)」とは、配列を昇順にソートされた状態にするために必要な要素の入れ替え回数を表す指標です。配列がすでにソートされている場合、反転数は 0 となり、逆に配列が完全に逆順に並んでいる場合、反転数は最大値になります。この記事では、配列内の反転数を数えるC++プログラムを実際に作成しながら、その考え方と実装方法をわかりやすく解説します。反転数とは配列内の2つの要素 a[i] と a[j] について、i < j かつ a[i] > a[j] が成り立つとき、このペアを「反転(inversion)」と呼びます。配列全体に存在する反転ペアの総数が反転数です