C++で絶対差が1以下となる要素の最大数を求める方法
n個の要素からなる配列が与えられたとします。この配列から、選んだ任意の2つの要素の絶対差が1以下になるように、最大でいくつの要素を選べるかを求める問題です。例えば、配列が [2, 2, 3, 4, 5] の場合、答えは3となり、要素数が最大となる組み合わせは「2, 2, 3」です。
解法の考え方
絶対差が0または1であるということは、選べる数値は「x」と「x + 1」の2種類に限られることを意味します。そこで、各要素の出現回数(頻度)を記録しておき、隣り合う2つの値の頻度の合計が最大になるところを探せば、それが求める答えとなります。
アルゴリズムの手順
- mapを使って、配列内の各要素の出現回数をカウントする
- 各キーkeyについて、key+1がマップ内に存在するかどうかを確認する
- 存在する場合は occurrence[key] + occurrence[key+1] を計算し、現在の最大値より大きければ更新する
- 最終的な最大値を答えとして返す
サンプルコード(C++)
#include <iostream>
#include <map>
using namespace std;
int maxElem(int arr[], int n) {
map<int,int> occurrence;
for(int i=0;i<n;++i){
if(occurrence[arr[i]])
occurrence[arr[i]] += 1;
else
occurrence[arr[i]] = 1;
}
int ans = 0, key;
map<int,int>:: iterator it=occurrence.begin();
while(it!=occurrence.end()) {
key = it->first;
++it;
if(occurrence[key+1]!=0)
ans=max(ans,occurrence[key]+occurrence[key+1]);
}
return ans;
}
int main(){
int arr[] = {2, 2, 3, 4, 5};
int n = sizeof(arr)/sizeof(arr[0]);
cout<<"Result is: " << maxElem(arr, n);
}実行結果
Result is: 3
計算量について
このアルゴリズムでは、まず配列を一度走査して頻度マップを作成します。std::mapへの挿入はO(log n)かかるため、ここでの計算量はO(n log n)です。その後、マップ内の各キーに対して定数時間の処理を行うため、全体の時間計算量はO(n log n)、空間計算量はO(n)となります。なお、順序が不要な場合はunordered_mapを使うことで、平均O(n)まで高速化できます。
-
C++を使って「数x + xの桁の合計 = n」となる数xを求める方法
ここでは、ある数nが与えられたとき、「数xとその桁の合計を足した値がnと等しくなる」ようなxを求める問題を扱います。例えば、nが21の場合、答えはx = 15となります。15の桁の合計は1 + 5 = 6なので、15 + 6 = 21 = nとなり、条件を満たすからです。この問題を解くには、シンプルなアプローチが有効です。0からnまでの数を順番に調べていき、各数値について「その数 + 桁の合計」がnと一致するかどうかを確認します。一致する数が見つかった時点でその値を返し、最後まで見つからなければ-1を返します。サンプルコード#include<iostream> using name
-
C++で「x + 桁の合計 = n」を満たす数xを見つける方法
この記事では、ある整数 n が与えられたとき、「x + x の各桁の合計 = n」という条件を満たす数 x を求める問題を解説します。例として、n = 21 の場合を考えてみましょう。このとき答えは x = 15 となります。なぜなら、15 の各桁の合計は 1 + 5 = 6 であり、15 + 6 = 21 となって、与えられた n と一致するからです。解き方のアプローチこの問題はシンプルな方法で解くことができます。1 から n まで順番に数を調べていき、それぞれの数について「その数自身 + 各桁の合計」が n と等しくなるかどうかを確認します。条件を満たす数が見つかった時点で処理を終了し、そ