C++で配列内の最頻出要素を求める方法
配列が与えられたとき、その中で最も多く出現する要素(最頻出要素)を見つける問題を考えてみましょう。まずは具体例から確認します。
入力例と出力例
入力
arr = [1, 2, 3, 3, 2, 2, 1, 1, 2, 3, 4]
出力
2
上記の配列では、2 が4回出現しており、他のどの要素よりも出現回数が多くなっています。
アルゴリズム1:ハッシュマップを使う方法
- 配列を初期化します。
- 各要素の出現回数を格納するためのマップ(unordered_map)を初期化します。
- 配列を走査しながら各要素の出現回数を数え、マップに保存します。
- マップを走査し、最も出現回数の多い要素を見つけます。
- その要素を返します。
この方法の時間計算量は O(n)、空間計算量は O(n) となり、効率的に最頻出要素を求められます。
アルゴリズム2:ソートを使う方法
- 配列を初期化します。
- 与えられた配列をソートします。
- 最大出現回数・結果・現在の要素の出現回数を保持する変数を用意します。
- ソート後は同じ要素が必ず隣り合うため、配列を一度走査するだけで最大出現回数の要素を見つけられます。
- 結果を返します。
この方法の時間計算量は O(n log n) です。追加のメモリをほとんど使わずに済む点が特徴です。
C++での実装
以下は、アルゴリズム1(ハッシュマップ方式)をC++で実装したコードです。
#include <bits/stdc++.h>
using namespace std;
int getMostFrequentNumber(int arr[], int n) {
unordered_map<int, int> elements;
for (int i = 0; i < n; i++) {
elements[arr[i]]++;
}
int maxCount = 0, res = -1;
for (auto i : elements) {
if (maxCount < i.second) {
res = i.first;
maxCount = i.second;
}
}
return res;
}
int main() {
int arr[] = { 1, 2, 3, 3, 2, 2, 1, 1, 2, 3, 4 };
int n = 11;
cout << getMostFrequentNumber(arr, n) << endl;
return 0;
}実行結果
上記のコードを実行すると、次の結果が出力されます。
2
このように、ハッシュマップを活用することで、配列内の最頻出要素を線形時間で簡単に求めることができます。
-
C++で配列内の各要素のサーパッサー(Surpasser)の数を求めるアルゴリズム
ある配列Aが与えられたとき、各要素の「サーパッサー(surpasser)」の数を求める問題を考えてみましょう。サーパッサーとは、現在注目している要素よりも右側に存在する、その要素より大きい値のことです。 例えば、A = {2, 7, 5, 3, 0, 8, 1} という配列の場合、サーパッサーの数は {4, 1, 1, 1, 2, 0, 0} となります。これは、先頭の「2」の右側には「7・5・3・8」という4つの大きな値が存在するためです。その他の要素についても同じルールで数えていきます。 アルゴリズムの考え方 解法は非常にシンプルです。2重のループを使用し、外側のループで各要素を順に取り上
-
C++ STLの配列アルゴリズム徹底解説!all_of・any_of・none_of・copy_n・iotaの使い方
C++11で追加されたSTLの配列アルゴリズムとは C++11以降、STL(標準テンプレートライブラリ)には配列やコンテナを効率的に扱うためのアルゴリズム関数が多数追加されました。これらの関数は主に <algorithm> ヘッダーに定義されており、ループ処理を自前で書く必要がなくなるため、コードの可読性と保守性が大きく向上します。ここでは、実践で特に役立つ5つの関数をサンプルコードとともに解説します。 1. all_of():すべての要素が条件を満たすか判定する all_of() は、コンテナ内のすべての要素が指定した条件を満たす場合に true を返す関数です。たとえば「配列