Beste Zeit zum Kaufen und Verkaufen von Aktien IV

Methode 1: Dynamische Programmierideen
und Algorithmen

Ähnlich wie bei anderen Aktienproblemen verwenden wir eine Reihe von Variablen, um den Status „Kauf“ zu speichern, und verwenden dann eine Reihe von Variablen, um den Status „Verkauf“ zu speichern. Dieses Problem kann durch dynamische Programmierung gelöst werden.

Wir verwenden , um den maximalen Gewinn in diesem Fall für genau jj Transaktionen für den Preis im \textit{kaufen}[i][j]kaufen[i][j]Array darzustellen, und halten derzeit einen Bestand in der Hand; verwenden , um genau jj Transaktionen darzustellen, und halten derzeit keinen Bestand in der Hand. Aktien, der maximale Gewinn in dieser Fall.\textit{Preise}[0..i]Preise[0..i]\textit{sell}[i][j]sell[i][j]

Dann können wir die Zustandsübergangsgleichung ableiten. Bei \textit{buy}[i][j]buy[i][j] prüfen wir, ob die aktuell gehaltene Aktie am Tag II gekauft wurde. Wenn es am Tag ii gekauft wird, dann halten wir die Aktie am Tag i-1i−1 nicht und der entsprechende Status ist \textit{sell}[i-1][j]sell[i−1][j ], und die Anschaffungskosten von \textit{prices}[i]prices[i] müssen abgezogen werden; wenn es nicht am Tag ii gekauft wird, dann halten wir am Tag i-1i−1 den entsprechenden Bestand in der Hand zum Status \textit{kaufen}[i-1][j]kaufen[i−1][j]. Dann können wir die Zustandsübergangsgleichung erhalten:

\textit{kaufen}[i][j] = \max \big\{ \textit{kaufen}[i-1][j], \textit{verkaufen}[i-1][j] - \textit{Preis }[ich groß\}

buy[i][j]=max{buy[i−1][j],sell[i−1][j]−price[i]}

Wenn es am Tag ii verkauft wird, halten wir die Aktie auf die gleiche Weise \textit{sell}[i][j]sell[i][j],am Tag i-1i−1 in der Hand, entsprechend dem Zustand \textit{buy}[i-1][j-1]buy[ i− 1][j−1], und der Verkaufsgewinn von \textit{prices}[i]prices[i] muss erhöht werden; wenn es nicht am ii. Tag verkauft wird, dann am i-1i−1 Tag haben wir Wenn Sie keine Aktien halten, ist der entsprechende Status \textit{sell}[i-1][j]sell[i−1][j]. Dann können wir die Zustandsübergangsgleichung erhalten:

\textit{sell}[i][j] = \max \big\{ \textit{sell}[i-1][j], \textit{buy}[i-1][j-1] + \textit {Preis}[i] \big\}

verkaufen[i][j]=max{verkaufen[i−1][j],kaufen[i−1][j−1]+Preis[i]}

Da nach Ablauf aller nn Tage der maximale Gewinn, der dem Nichtvorhandensein von Lagerbeständen entspricht, unbedingt auf den maximalen Gewinn zurückzuführen sein muss, der dem Halten von Lagerbeständen entspricht. Die Anzahl der abgeschlossenen Transaktionen ist jedoch nicht immer besser (z. B. das Array). monoton fallend ist \textit{Preise}Preise, ist es optimal, wenn wir keine Transaktionen durchführen), daher ist die endgültige Antwort \textit{sell}[n-1][0..k]sell[n−1][0..k]der Maximalwert in .

Detail

In der obigen Zustandsübergangsgleichung ist die Bestimmung der Randbedingungen ein sehr wichtiger Schritt. Wir können darüber nachdenken, allen \textit{kaufen}[0][0..k]kaufen[0][0..k]und \textit{sell}[0][0..k]sell[0][0..k]allen Grenzen zu setzen.

Da es für \textit{buy}[0][0..k]buy[0][0..k] nur einen \textit{Preise}[0]Preise[0]eindeutigen Aktienpreis gibt, können wir keine Transaktionen durchführen, dann können wir alle \textit{kaufen}[0][1..k]kaufen[0][1..k]auf ein A sehr setzen Ein kleiner Wert weist auf einen illegalen Zustand hin. Und für \textit{kaufen}[0][0]kaufen[0][0], ist ihr Wert - , das heißt, „wir haben die Aktie zum Preis -\textit{Preise}[0]−Preise[0]am Tag 00 gekauft“ ist die einzige Möglichkeit, das Bedürfnis, die Aktie zu halten, zu befriedigen.\textit{Preise}[0]Preise[0]

Für \textit{sell}[0][0..k]sell[0][0..k] können wir auf ähnliche Weise alle \textit{sell}[0][1..k]sell[0 ][ 1..k] ist auf einen sehr kleinen Wert eingestellt, was auf einen illegalen Zustand hinweist. Für \textit{sell}[0][0]sell[0][0] beträgt der Wert 00, d. h. „wir machen am Tag 00 nichts“ ist die einzige Möglichkeit, die Anforderung zu erfüllen, dass wir keine Vorräte halten . .

Nachdem wir die Grenzen festgelegt haben, können wir eine Doppelschleife im Bereich von i\in [1,n), j \in [0, k]i∈[1,n),j∈[0,k] verwenden Zustand ausführen überweisen. Es ist zu beachten, dass die Zustandsübergangsgleichung von \textit{sell}[i][j]sell[i][j] \textit{buy}[i-1][j-1]buy[i−1] enthält. [j−1], wenn j=0j=0, stellt es einen illegalen Zustand dar. Wenn also j=0j=0, müssen wir nicht \textit{sell}[i][j]sell[i][j] Übertragen Sie es einfach, damit es bei 00 bleibt.

Als letztes ist zu beachten, dass der Maximalwert von kk in dieser Frage 10 ^ 910 erreichen kann 

Code

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if (prices.empty()) {
            return 0;
        }

        int n = prices.size();
        k = min(k, n / 2);
        vector<vector<int>> buy(n, vector<int>(k + 1));
        vector<vector<int>> sell(n, vector<int>(k + 1));

        buy[0][0] = -prices[0];
        sell[0][0] = 0;
        for (int i = 1; i <= k; ++i) {
            buy[0][i] = sell[0][i] = INT_MIN / 2;
        }

        for (int i = 1; i < n; ++i) {
            buy[i][0] = max(buy[i - 1][0], sell[i - 1][0] - prices[i]);
            for (int j = 1; j <= k; ++j) {
                buy[i][j] = max(buy[i - 1][j], sell[i - 1][j] - prices[i]);
                sell[i][j] = max(sell[i - 1][j], buy[i - 1][j - 1] + prices[i]);   
            }
        }

        return *max_element(sell[n - 1].begin(), sell[n - 1].end());
    }
};


Beachten Sie, dass in der Zustandsübergangsgleichung \textit{buy}[i][j]buy[i][j] und \textit{sell}[i][j]sell[i][j] beide bei \textit beginnen { buy}[i-1][..]buy[i−1][..] und \textit{sell}[i-1][..]sell[i−1][..] werden übertragen, Daher können wir für die Zustandsübertragung eindimensionale Arrays anstelle von zweidimensionalen Arrays verwenden, das heißt:

\begin{cases} b[j] \leftarrow \max \big\{ b[j], s[j] - \textit{price}[i] \big\} \\ \\ s[j] \leftarrow \ max \big\{ s[j], b[j-1] + \textit{price}[i] \big\} \end{cases}
  
b[j]←max{b[j],s[j]−Preis[i]}
s[j]←max{s[j],b[j−1]+Preis[i]
}
 

Solche Zustandsübergangsgleichungen werden aufgrund der Zustandsabdeckung unterschiedlich. Wenn wir beispielsweise \textit{b}bzuerst ss und dann ss berechnen, wird bei der Berechnung von s[j]s[j] der Wert des Elements b[j-1]b[j−1] in die Zustandsübergangsgleichung einbezogen überschrieben. Das heißt, es hätte \textit{kaufen}[i-1][j-1]kaufen[i−1][j−1]von einer zweidimensionalen Darstellung übertragen werden sollen, aber jetzt ist es geworden\textit{kaufen}[i-1][j-1]kaufen[i−1][j−1]

Aber es ist immer noch richtig. Wir betrachten die Zustandsübergangsgleichung von \textit{buy}[i][j-1]buy[i][j−1]:

b[j-1] \leftarrow \textit{kaufen}[i][j-1] = \max \big\{ \textit{kaufen}[i-1][j-1], \textit{verkaufen}[ i-1][j-1] - \textit{Preis}[i] \big\}
b[j−1]←kaufen[i][j−1]=max{kaufen[i−1][j−1],verkaufen[i−1][j−1]−Preis[i]}

Dann lautet die Zustandsübergangsgleichung von s[j]s[j] tatsächlich:

s[j] \leftarrow \max \big\{ s[j], \textit{kaufen}[i-1][j-1] + \textit{Preise}[i], \textit{verkaufen}[i- 1][j-1] \big\}
s[j]←max{s[j],buy[i−1][j−1]+prices[i],sell[i−1][j−1 ]}

Warum erscheint der Begriff \textit{sell}[i-1][j-1]sell[i−1][j−1] in der Zustandsübergangsgleichung von s[j]s[j]? Tatsächlich wird die Aussage „Kauf zu \textit{Preisen}[i]Preisen[i] am Tag II und Verkauf zu \textit{Preisen}[i]Preisen[i] am selben Tag“ als Transaktion betrachtet das entsprechende Einkommen beträgt:

\textit{sell}[i-1][j-1] - \textit{prices}[i] + \textit{prices}[i]
sale[i−1][j−1]−prices[i]+ Preise[i]

Das heißt, \textit{sell}[i-1][j-1]sell[i−1][j−1] selbst. In diesem Fall einer Transaktion innerhalb desselben Tages beträgt das Einkommen Null. Es bringt kein zusätzliches Einkommen und hat daher keinen Einfluss auf die endgültige Antwort. Die Zustandsübergangsgleichung ist im Wesentlichen immer noch korrekt.

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if (prices.empty()) {
            return 0;
        }

        int n = prices.size();
        k = min(k, n / 2);
        vector<int> buy(k + 1);
        vector<int> sell(k + 1);

        buy[0] = -prices[0];
        sell[0] = 0;
        for (int i = 1; i <= k; ++i) {
            buy[i] = sell[i] = INT_MIN / 2;
        }

        for (int i = 1; i < n; ++i) {
            buy[0] = max(buy[0], sell[0] - prices[i]);
            for (int j = 1; j <= k; ++j) {
                buy[j] = max(buy[j], sell[j] - prices[i]);
                sell[j] = max(sell[j], buy[j - 1] + prices[i]);   
            }
        }

        return *max_element(sell.begin(), sell.end());
    }
};


Komplexitätsanalyse

Zeitkomplexität: O(n\min(n, k))O(nmin(n,k)), wobei nn die Größe des Arrays \textit{prices}prices ist, also die Zeit, die wir zur Nutzung benötigen eine Doppelschleife für dynamische Programmierung.

Raumkomplexität: O(n\min(n, k))O(nmin(n,k)) oder O(\min(n, k))O(min(n,k)), je nachdem, wie wir zwei verwenden Dimensionales Array oder eindimensionales Array für dynamische Programmierung.

                                                                                                                                                         

Supongo que te gusta

Origin blog.csdn.net/aliyonghang/article/details/128328280
Recomendado
Clasificación