2016-07-12 17 views
0

"Introduction To Algorithms"を読んでいます。最大部分配列問題(第4章)では、配列の最大値と最小値を見つけるだけで、株式の売買の最大利益を計算することはできないと主張しています。著者は、0(n^2)時間が必要な購入日と売り日の可能な組み合わせをすべて計算することにより、ブルートフォースなどの代替案を話します。もう1つの選択肢は、価格配列の日々の変化の最大部分配列を見つけることです。株式の利益を最大化する(最大サブアレイ)

しかし、私は0(n)時間かかると最大利益を見つけるアルゴリズムをコーディングしました。これは0(n)であり、最大のサブアレイ問題は0(n log n)である。しかし、私は著者が間違っていることはできないことを知っています。どこが間違っていますか?私のアルゴリズムは正しいですか?

#include <stdio.h> 
#include <limits.h> 

int main(void) 
{ 
    int A[8]={10,8,3,9,7,4,5,10,4}; 
    int i,max,min,currmax,prevmax,n=8; 

    max=INT_MIN; 
    min=INT_MAX; 
    for(i=0;i<n;i++) 
    { 
     if(A[i]>max) 
     { 
      max=A[i]; 
      prevmax=currmax; 
      currmax=max-min; 
     } 
     if(A[i]<min) 
     { 
      min=A[i]; 
      max=INT_MIN; 
     } 

    } 

    if(prevmax>currmax) 
     printf("%d",prevmax); 
    else 
     printf("%d",currmax); 

    return 0; 
} 
GeeksForGeeksに示すよう

http://www.geeksforgeeks.org/divide-and-conquer-maximum-sum-subarray/)、株価の日々の変化のための入力は、[] = { - 2、-5、6、-2、-3、1、5、 -6}である。 私は基本価格を10とし、アルゴリズムをA [] = {10,8,3,9,7,4,5,10,4}として実行しました。

入力:10,8,3,9,7,4,5,10,4

出力:7

+0

あなたが言うように、解は最大のシーケンス問題によって与えられます。しかし、最大シーケンス問題は、O(n)空間とO(1)時間で[解決](https://en.wikipedia.org/wiki/Maximum_subarray_problem#Kadane.27s_algorithm)です。 O(n log n)とはどこですか(どのページ)ですか? –

+0

あなたのアルゴリズムは正しい考えを持っているようです。しかし、私はあなたがprevmaxを取り出し、 'if(max-min> currmax)currmax = max-min;'を実行し、あなたの答えとして 'currmax'を表示するだけでよいと思います。そうしないと、答えがprevmaxの前に来ると間違っています。また、利益がない場合には、 'currmax'を0に初期化する必要があります。 –

+0

@LawrenceWu:ページ74、CLRS 3E。それは0(n lg n)と言います。ええ、prevmaxは必要ありませんでした。 –

答えて

2

ここにあなたがあなたが売買を通じて行うことができる最大の利益を探していますストック(一度重要です)。

あなたのアルゴリズムでは、株式の最低ストライキ価格から最高の利益が生じると仮定しています。 これは間違っている:A[] = {10,23,6,12,4,1,0,3}、プログラムの出力3と、例えば最大の利点は、明らかに13であるのに対し(Coliruにプルーフ)

最適な利益の特徴ストック固定具のデルタ配列を計算することである(A[ ]={-2, -5, 6, -2, -3, 1, 5, -6}あなたが引用した配列)、最大部分配列を取得します。私の例ではF[] = {13, -17, 6, -8, -3, -1, 3}、最大サブアレイは{13}です。結局、必要な利益は最大サブアレイの合計です。

もう1つの方法は、配列の最小値のタブを反復して保持することです。A[0..i-1]iは1からn-1の範囲です)。インデックスi(すなわち、時刻iでの販売)では、差額がA[i] - min(A[0..i-1])、またはその差がマイナスの場合は0が最良です。これらの相違点の最大値を把握する必要があります。最後に、前記最大値が所望の結果である。

これは基本的にアルゴリズムの機能です。明確な実装がrunning here

#include <stdio.h> 
#include <limits.h> 

int main(void) 
{ 
    int A[8]={10,23,6,12,4,1,0,3}; 
    int i,min_i, profit_i, best_profit=0,n=8; 

    min_i=A[0]; 
    for(i=1;i<n;i++) 
    { 
     profit_i = A[i] - min_i; 
     best_profit = (profit_i > best_profit) ? profit_i : best_profit; 

     if(A[i]<min_i) 
     { 
      min_i=A[i]; 
     } 

    } 

    printf("Best profit: %d", best_profit); 
    return 0; 
} 

見つけることができ、不要なローカル変数がありますが、私は、彼らが見て、ロジックが容易になりました。

+0

仮定は部分的にしか間違っています。時刻tで販売される最高の利益は、時刻t前の最低価格から生じる。このようにして、OPのソリューションを回収することはまだ可能です。差分を取って最適な和を計算することは、せいぜい努力の浪費である(これらの操作は逆になります)、最悪ではO(n)メモリの無駄であるため、デルタ配列は必ずしも「最良の特性」であるとは限りません。 –

+0

コードは13として出力され、 '(max-min> currmax)currmax = max-min;'と@LawrenceWuによって指摘される 'prevmax'を伴わないで動作します。 –

+0

@LawrenceWuこれは、ストックが時間tで販売された場合、インデックス「t」の要素が「最良利益」となるサイズ「n-1」の配列を計算し、次にその配列の最大値を取り出すことを必要とする。それでも 'O(n)'メモリの無駄です。この配列は 'O(n)'ですが、これは最大部分配列よりも優れています – Rerito

関連する問題