C++でソート済み配列から25%を超えて出現する要素を効率的に見つける方法
問題の概要
配列Aが与えられます。配列には複数の要素が含まれており、その中には重複する要素もあります。この問題では、配列全体の25%を超える割合で出現している要素を1つ見つけて返す必要があります。
例えば、A = [1, 2, 4, 4, 4, 4, 5, 5, 6, 6, 7, 7] の場合を考えてみましょう。この配列のサイズは12なので、25%に相当するのは3回です。ここで「4」は4回出現しており、25%を超えているため、答えは「4」となります。
解決のアプローチ
この問題は、ハッシュマップ(unordered_map)を使って各要素の出現回数を数えることで、シンプルに解くことができます。手順は以下の通りです。
- 配列の各要素を順に読み込み、それぞれの出現回数(頻度)をハッシュマップに記録します。
- ある要素の出現回数が配列サイズの25%(n / 4)を超えた時点で、その要素を結果として返します。
実装例(C++)
理解を深めるために、以下のC++での実装例を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int findSpecialInteger(vector<int>& arr) {
int n = arr.size();
int req = n / 4;
unordered_map <int, int> m;
int ans = -1;
for(int i = 0; i < n; i++){
m[arr[i]]++;
if(m[arr[i]] > req)ans = arr[i];
}
return ans;
}
};
main(){
Solution ob;
vector<int> c = {1,2,4,4,4,4,5,5,6,6,7,7};
cout << ob.findSpecialInteger(c);
}
入力
[1,2,4,4,4,4,5,5,6,6,7,7]
出力
4
計算量と補足
上記のハッシュマップを使う方法の時間計算量はO(n)、空間計算量はO(n)となります。実装がシンプルで分かりやすいのが特徴です。
なお、配列がソート済みであることを活かすと、さらに効率的な解法も存在します。25%を超えて出現する要素は、必ず位置 n/4、n/2、3n/4 のいずれかをまたいで連続して現れるため、これら3つの候補位置にある要素について二分探索で出現範囲を調べれば、O(log n)の時間計算量で答えを求めることができます。大規模なデータを扱う場合は、こちらの手法も検討するとよいでしょう。
-
2つ以上の数値(配列)の最大公約数(GCD)を求めるC++プログラム
2つの数の「公約数」とは、その両方の数を割り切ることができる数のことです。例えば、12の約数は 1、2、3、4、6、12 です。18の約数は 1、2、3、6、9、18 です。したがって、12と18の共通の約数(公約数)は 1、2、3、6 となり、その中で最も大きいものが「最大公約数(GCD: Greatest Common Divisor)」と呼ばれます。数学では、2つの整数 a と b の最大公約数は gcd(a, b) と表記され、この場合 gcd(12, 18) = 6 となります。最大公約数はさまざまな場面で重要な役割を果たします。例えば、2つの数の「最小公倍数(LCM: Least
-
C++で3つ以上の数値(または配列)の最大公約数(GCD)を求める方法
本記事では、3つ以上の数値の最大公約数(GCD)をC++で求める方法を解説します。2つの数値のGCDを求めるのは簡単ですが、3つ以上の数値を扱う場合はGCDの結合法則を利用します。例えば、{w, x, y, z} のGCDを求めたい場合、以下のように段階的に計算します。まず {gcd(w, x), y, z} を計算次に {gcd(gcd(w, x), y), z) を計算最後に {gcd(gcd(gcd(w, x), y), z)} を計算この手法を配列に適用すれば、任意の個数の数値に対してGCDを簡単に求めることができます。アルゴリズムgcd(a, b)begin