C++で最初に増加し、その後減少する配列の最大要素を二分探索で見つける方法
最初に増加し、その後減少していく配列(ビトニック配列と呼ばれます)から最大値を見つける方法を解説します。例えば、配列の要素が A = [8, 10, 20, 80, 100, 250, 450, 100, 3, 2, 1] の場合、最大値は 450 となります。
この問題は線形探索でも解けますが、二分探索(バイナリサーチ)を活用すれば、O(log n) という高速な計算量で最大値を効率的に求めることができます。
二分探索による解法のポイント
二分探索では、中央の要素(mid)とその隣接要素との大小関係に注目し、以下の3つの条件で場合分けを行います。
- mid が両隣の要素よりも大きい場合 → mid が最大値
- mid が次の要素より大きく、前の要素より小さい場合 → 最大値は mid の左側に存在する
- mid が次の要素より小さく、前の要素より大きい場合 → 最大値は mid の右側に存在する
C++での実装例
#include<iostream>
using namespace std;
int getMaxElement(int array[], int left, int right) {
if (left == right)
return array[left];
if ((right == left + 1) && array[left] >= array[right])
return array[left];
if ((right == left + 1) && array[left] < array[right])
return array[right];
int mid = (left + right)/2;
if ( array[mid] > array[mid + 1] && array[mid] > array[mid - 1])
return array[mid];
if (array[mid] > array[mid + 1] && array[mid] < array[mid - 1])
return getMaxElement(array, left, mid-1);
else
return getMaxElement(array, mid + 1, right);
}
int main() {
int array[] = {8, 10, 20, 80, 100, 250, 450, 100, 3, 2, 1};
int n = sizeof(array)/sizeof(array[0]);
cout << "The maximum element is: " << getMaxElement(array, 0, n-1);
}実行結果
The maximum element is: 450
まとめ
このアルゴリズムは、配列が「増加 → 減少」という形状(ビトニック配列)であることを前提としています。再帰的に探索範囲を半分に絞り込んでいくため、要素数が多い配列でも非常に効率的に最大値を見つけられるのが特徴です。
-
C++で配列内のab=cdとなるすべてのペア(a, b)と(c, d)を見つける方法
配列Aが与えられたとき、その中から積が等しくなる2つのペア(a, b)と(c, d)、つまりab = cdを満たす組み合わせを見つける問題を考えます。例えば、配列A = [3, 4, 7, 1, 2, 9, 8]の場合、(4, 2)と(1, 8)というペアが条件を満たします。実際に4×2 = 8、1×8 = 8となり、積が一致していますね。この問題を効率的に解くには、ハッシュテーブル(C++ではunordered_map)を活用します。すべてのペアの積を順に計算し、同じ積がすでにハッシュテーブルに登録されているかどうかを確認することで、条件を満たすペアを検出できます。アルゴリズムの手順iを0か
-
配列の要素の積の最初の桁を求めるC++プログラム
はじめにこの記事では、与えられた配列のすべての要素を掛け合わせた積の、最初の桁(最上位の桁)を求めるプログラムについて解説します。例として、次のような配列が与えられたとします。arr = {12, 5, 16}これらの要素の積は、12 × 5 × 16 = 960 となります。したがって、求める結果、つまり積の最初の桁は「9」になります。アルゴリズム変数 prod を 1 で初期化するループを使い、配列の各要素を順番に prod に掛けていくprod が 10 以上である間、prod を 10 で割り続ける残った一桁の値が、積の最初の桁となるサンプルコード#include <bits/s