C++で解く最大消去値(Maximum Erasure Value)― スライディングウィンドウによる効率的な実装
正の整数からなる配列が与えられたとき、すべての要素が一意(重複なし)である部分配列を1つだけ消去することを考えます。この操作で得られるスコアは、消去した部分配列の要素の総和です。
ここでの目的は、ちょうど1つの部分配列を消去したときに得られる最大の合計値を返すことです。
なお、配列 arr が a の部分配列であるとは、a[l], a[l+1], …, a[r] という形で表される連続した部分列と一致することを意味します。
入力例と出力例
例1
arr[ ] = { 1, 2, 4, 5, 6 }出力:
17
説明: 最適な部分配列は {2, 4, 5, 6} です。その総和は 17 になります。
例2
arr[ ] = { 5, 3, 1, 3, 5, 3, 1, 3, 5 }出力:
9
説明: 最適な部分配列は {5, 3, 1} または {1, 3, 5} です。いずれも総和は 9 になります。
この問題へのアプローチ
この問題はスライディングウィンドウ(Sliding Window)の概念を用いて解きます。このテクニックを使うと、二重ループを単一のループに変換でき、時間計算量を大幅に削減できます。
具体的には、左右2つのポインタ(left / right)とウィンドウの合計値 win を用意します。配列を先頭から走査しながら、現在のウィンドウ内の要素がすでにハッシュセット(HashSet)に存在するかどうかを判定します。
- すでに存在する場合 → 重複がなくなるまで左端の要素をセットから取り除き、ウィンドウを縮めます。
- 存在しない場合 → その要素をハッシュセットに追加し、ウィンドウの合計値に加算します。
各ステップで「これまでの結果」と「現在のウィンドウの合計値」を比較し、大きい方を結果として保持します。
アルゴリズムの手順
- 正の整数からなる配列を入力として受け取ります。
- 整数型関数 maximumUniqueSubarray(vector<int>& arr) が配列を受け取ります。
- ポインタ i、j とウィンドウ合計 win を初期化し、配列を走査します。現在の要素がハッシュセットに存在すれば、重複が解消されるまで左端を除去してウィンドウを移動します。存在しなければ要素をセットに挿入し、win に加算します。
- 結果 result と win の最大値を常に更新します。
- 最終的な result を返します。
C++による実装例
#include<bits/stdc++.h>
using namespace std;
int maximumUniqueSubarray(vector<int>& arr) {
int result = 0;
unordered_set<int> hashset;
for (int i = 0, j = 0, win = 0; j < arr.size(); j++) {
while (hashset.find(arr[j]) != hashset.end()) {
hashset.erase(arr[i]);
win -= arr[i];
i++;
}
hashset.insert(arr[j]);
win += arr[j];
result = max(result, win);
}
return result;
}
int main(){
vector<int>nums;
nums<<5,3,1,3,5,3,1,3,5;
cout<<maximumUniqueSubarray(nums)<<endl;
return 0;
}実行結果
上記のコードを実行すると、次の出力が得られます。
9
この実装では、各要素が高々1回ずつ追加・削除されるため、時間計算量は O(n)、ハッシュセットに必要な空間計算量も O(n) となり、非常に効率的に最大消去値を求めることができます。
-
C++のlog1p()関数とは?使い方とサンプルコードをわかりやすく解説
C++のlog1p()関数の概要C++のlog1p()関数は、任意の数値 a に対して「(a + 1) の自然対数(底が e の対数)」を計算するための関数です。戻り値として (a+1) の自然対数の値が返されます。なお、引数に -1 未満の値 を渡した場合は、有効な結果が得られないため NaN(Not a Number) が返される点に注意が必要です。数学的な表現log1p() の動作は、次の数式で表すことができます。log1p(a) = base-e log(a+1)log1p()の構文C++における log1p() 関数の構文は以下のとおりです。float log1p(float var
-
Pythonで「最大消去値」を求めるプログラム ― スライディングウィンドウ法による解説
問題の概要 正の整数のみを含む配列 nums が与えられます。この中から要素がすべて一意(重複なし)である部分配列をちょうど1つ選んで「消去」し、その部分配列に含まれる要素の合計値をスコアとして得ます。求めたいのは、この操作で取得できるスコアの最大値です。 例えば、入力が nums = [6,3,2,3,6,3,2,3,6] の場合、出力は 11 になります。これは、最適な部分配列が [6,3,2] または [2,3,6] のいずれかであり、どちらも合計が 11 になるためです。 解き方のアプローチ:スライディングウィンドウ この問題はスライディングウィンドウ(尺取り法)を使うことで効率的に