私が試した次のアルゴリズムは、最初に配列をソートするために使用されるアルゴリズムの順序になります。たとえば、最初の配列が二分木ソートでソートされている場合、最良の場合は O(n)、平均の場合は O(n log n) になります。
アルゴリズムの要点:
配列がソートされます。ソートされた値と対応する古いインデックスが保存されます。二分探索木は、対応する古いインデックスから作成されます。これは、現在の値よりも小さい値に遭遇することなく前後に移動できる距離を決定するために使用されます。これにより、可能な最大のサブ配列が得られます。
質問の配列[1,5,3,5,4,1]での方法を説明します
1 5 3 5 4 1
-------------------------
array indices => 0 1 2 3 4 5
-------------------------
この配列はソートされています。値とそのインデックスを昇順で保存します。これは次のようになります。
1 1 3 4 5 5
-------------------------
original array indices => 0 5 2 4 1 3
(referred as old_index) -------------------------
値と古いインデックスの両方を参照することが重要です。連想配列のように。
明確にするためのいくつかの用語:
old_index は、要素の対応する元のインデックス (元の配列のインデックス) を参照します。
たとえば、要素 4 の場合、old_index は 4 です。current_index は 3 です。
一方、 current_index は、ソートされた配列内の要素のインデックスを参照します。current_array_value は、ソートされた配列内の現在の要素値を参照します。
pre は順不同の先行者を指します。succ は順不同の後継者を指します
また、最小値と最大値は、ソートされた配列の最初と最後の要素 (それぞれ min_value と max_value) から直接取得できます。
さて、ソートされた配列で実行するアルゴリズムは次のとおりです。
アルゴリズム:
一番左の要素から進みます。
ソートされた配列の左からの各要素に対して、このアルゴリズムを適用します
if(element == min_value){
max_sum = element * array_length;
if(max_sum > current_max)
current_max = max_sum;
push current index into the BST;
}else if(element == max_value){
//here current index is the index in the sorted array
max_sum = element * (array_length - current_index);
if(max_sum > current_max)
current_max = max_sum;
push current index into the BST;
}else {
//pseudo code steps to determine maximum possible sub array with the current element
//pre is inorder predecessor and succ is inorder successor
get the inorder predecessor and successor from the BST;
if(pre == NULL){
max_sum = succ * current_array_value;
if(max_sum > current_max)
current_max = max_sum;
}else if (succ == NULL){
max_sum = (array_length - pre) - 1) * current_array_value;
if(max_sum > current_max)
current_sum = max_sum;
}else {
//find the maximum possible sub array streak from the values
max_sum = [((succ - old_index) - 1) + ((old_index - pre) - 1) + 1] * current_array_value;
if(max_sum > current_max)
current_max = max_sum;
}
}
例えば、
元の配列は
1 5 3 5 4 1
-------------------------
array indices => 0 1 2 3 4 5
-------------------------
ソートされた配列は
1 1 3 4 5 5
-------------------------
original array indices => 0 5 2 4 1 3
(referred as old_index) -------------------------
最初の要素の後:
max_sum = 6 [1*6 に減少します]
0
2 番目の要素の後:
max_sum = 6 [1*6 に減少します]
0
\
5
3 番目の要素の後:
0
\
5
/
2
inorder トラバーサルの結果: 0 2 5
アルゴリズムを適用し、
max_sum = [((成功 - old_index) - 1) + ((old_index - pre) - 1) + 1] * current_array_value;
max_sum = [((5-2)-1) + ((2-0)-1) + 1] * 3 = 12
current_max = 12 [可能な最大値]
4 番目の要素の後:
0
\
5
/
2
\
4
inorder トラバーサルの結果: 0 2 4 5
アルゴリズムを適用し、
max_sum = 8 [これは 12 未満であるため破棄されます]
5 番目の要素の後:
max_sum = 10 [2 * 5 に減少、8 より小さいため破棄]
最後の要素の後:
max_sum = 5 [1 * 5 に減少、8 未満であるため破棄]
このアルゴリズムは、配列のソートに最初に使用されるアルゴリズムの順序になります。たとえば、最初の配列がバイナリ ソートでソートされている場合、最良の場合は O(n)、平均の場合は O(n log n) になります。
スペースの複雑さは O(3n) [O(n + n + n)、ソートされた値の n、古いインデックスの別の n、および BST の構築の別の n] になります。しかし、これについてはよくわかりません。アルゴリズムに関するフィードバックをお待ちしております。