ブルートフォースアルゴリズムではいくつかの最適化が可能です。
右に続くすべてのデータから計算された可能な合計を各インデックスに格納するアルゴリズムを作成できます。その情報は、再帰のバックトラッキング中に埋められます。
例:簡略化するために、前半の合計を最大化し、後半の合計を最小化することのみを検討します。
[4, 1, 8, 2, 4, 1, 4]
アルゴリズムは、配列の最後の要素に向けて深さ優先行き、その後、唯一の右に以下のものを考慮すると、そこに最高の合計を格納します。右には何もないので、合計は4です。しかし、最小化したいときは、符号を切り替えます。そこで、次のようなものを保存します。
[4, 1, 8, 2, 4, 1, 4]
-4
次に戻ってきます。現時点では2つの可能性があります。1をそのまま残すか、または周囲の値の平均を使用します(つまり、4):
[4, 1, 8, 2, 4, 1, 4]
-4
-5
[4, 1, 8, 2, 4, 4, 4]
-4
-8
両方の値-5及び-8値1について、我々は-5を見つけることができるように、ハッシュに保存され、値4のために、我々は-8を見つけることができます。
アルゴリズムの特定のポイントで、(1ではなく)2番目の配列要素で値6を試してから、再度再帰します。 1つ前の要素に到達すると、可能な値は再び1または4になります(他に何も変更されていない場合)ので、深く反復する必要はありません。そのインデックスで維持しているハッシュからの合計です。
このシステムでは、大規模な配列で多くの節約効果を得ることができます。実際に必要なときにアルゴリズムが再帰的に深くなるようにします。明らかに、それはスペースの点でコストがかかります。
次に、アルゴリズム全体をもう一度実行することができますが、その後、符号を入れ替えることができます。これらの2つの結果のうち、最良の解が取られ、絶対値が最大になります。
おそらく変更された要素の値を関数の引数として渡すことによって、複数の配列を作成することを避けることができ、入力配列で作業することができます。一方、各インデックスで作成されたハッシュにはいくらかのスペースが必要です。
function getMaxSum(a) {
// Index of the element in the middle. If integer,
// the element at this index will not play a role in any sum:
var mid = (a.length-1)/2;
// Two results, one that maximises the left sum and minimises the right sum
// The other minimises the left and maximises the right:
var result, result2, b;
function recurse(prevVal, index, sign, hash = []) {
var val, nextVal, sum, result, avg;
val = a[index];
if (index >= a.length-1) {
// At the last element there are no choices left:
return { sum: -sign*(prevVal+val), nextVal: val, hash: [] };
}
if (!hash[index]) hash[index] = [];
nextVal = a[index+1];
result = { sum: -Infinity, nextVal: 0, hash: hash[index] };
// Loop through the 2 possibilities (in general): take value as is, or
// take the average of previous and next value:
while (true) {
// If the result from this position onward is not know, calculate
// it via a recursive call:
if (!hash[index][val]) hash[index][val] = recurse(val, index+1, sign, hash);
// Add the previous value to the best sum at this point, using the appropriate sign,
// and store the result in a hash table, for future reference:
sum = hash[index][val].sum + (index-1 > mid ? -1 : index-1 < mid ? 1 : 0) * sign * prevVal;
if (sum > result.sum) {
result.sum = sum;
result.nextVal = val;
}
if (prevVal % 2 || nextVal % 2 || (avg = (prevVal + nextVal)/2) === val) break;
val = avg;
}
return result;
}
// Calculate both results
result = recurse(a[0], 1, 1, []);
result2 = recurse(a[0], 1, -1, []);
// Pick the best one.
if (Math.abs(result2.sum) > Math.abs(result.sum)) result = result2;
// Rebuild the array corresponding to the best result:
b = [a[0]];
while (result) {
b.push(result.nextVal);
result = result.hash[result.nextVal];
}
return b;
}
// Sample data
var a = [4, 1, 8, 2, 4, 1, 4];
console.log(' input: ' + a);
// Apply algorithm
var b = getMaxSum(a, 1);
// Print result
console.log('result: ' + b);
StackOverflowのは**ない**宿題である:ここでは
は、従うことは簡単でなければなりませんので、私は、任意の派手な機能を使用しなかったでJavaScriptにおけるアルゴリズムであり、サービス。これは毎日何回言わなければならないのですか? : – byxor
これは難しい問題のようです。問題の原因を教えてください。 – Tempux
あなたのニーズに合った答えがありましたか? – trincot