LeetCode質問122-株式を売買するのに最適な時期II-Python
トピック
配列が与えられた場合、そのi番目の要素は、i番目の日の特定の株式の価格です。
あなたが得ることができる最大の利益を計算するためのアルゴリズムを設計します。できるだけ多くのトランザクションを完了することができます(株式を複数回売買する)。
注:複数の取引に同時に参加することはできません(再度購入する前に前の株式を売却する必要があります)。
例:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出,
这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,
这笔交易所能获得利润 = 6-3 = 3 。
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出,
这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
ヒント:
1 <= prices.length <= 3 * 10 ^ 4
0 <= prices [i] <= 10 ^ 4
公式ソリューション1:DP動的計画法1
全体的なアイデア:毎日利益を書き留めます。i日は、株式を保有しているかどうかの2つのステータスしかないことを考慮すると、当日の株式の保有ステータスは、前日の保有株式または同日に購入した株式を継承する場合があります。同様に、当日の株式を保有していない状態は、前日の株式を保有していない状態または当日の株式を売却している状態を継承する場合があります。株を持たない最後の日を取ることは問題の解決策です。
説明:答えは、最終日の最大利益、つまり各前日の最大利益を求めています。
アルゴリズム
i日の利益dp [i]、株式が保有されていない場合のi日の利益dp [i] [0]、および株式が保有されている場合のi日の利益dp [i] [1]
を記録します。開催されたときに、DP [I] [0]は、[I] [0]は前日----- DPに株式を保持していないから来て、私の日に、DPの株式を保持していない状態である遷移状態、 [i-1] [0]
または前日の保有株式+当日のディッシュアウト収入----- dp [i-1] [1] +価格[i]のいずれか当日の最大利益
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
同様に、i日目の株式保有の利益については、dp [i] [1]は前日の株式保有から生じます----- dp [i-1] [1]
または前日の株式保有なし-その日の購入費用dp [i-1] [0]-価格[i]、その日の最も収益性の高い方
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
最終的な答えは、最終日に株式を売却した後の利益として理解できます。dp[n-1] [0](nは合計日数)
コード
def maxProfit(prices) -> int:
if not prices:
return 0
n = len(prices)
dp = [[0]*2 for _ in range(n)]
# dp[i][0]表示第i天不持有股票, dp[i][1]表示第i天持有股票
dp[0][0], dp[0][1] = 0, - prices[0]
for i in range(1, n):
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
return dp[n-1][0]
複雑さの分析
時間計算量:O(n)。ここで、nは配列の長さです。合計2nの状態があり、各状態遷移の時間計算量はO(1)であるため、時間計算量はO(2n)= O(n)です。
スペースの複雑さ:O(n)。動的計画法ですべての状態を格納するために、O(n)O(n)空間を開く必要があります。
公式ソリューション2:欲張り
全体的な考え方:この質問で貪欲を使用することは、頭の体操のようなものです。取引の数や手数料に制限はありません。毎日株式を売ることができるので、各取引の利益を0より大きく合計します。あなたが昨日より今日より多くのお金を稼ぐ限り売る。
コード
def maxProfit(prices) -> int:
# 任意两天的收益等于连续每天买入卖出收益的总和,如果要得到最大值,
# 那么需要连续每天交易时只取收益为正数的那天即可
N = len(prices)
res = 0
for i in range(N-1):
if prices[i] < prices[i+1]:
res = prices[i+1] - prices[i] + res
return res
複雑な分析
時間計算量:O(n)。ここで、nnは配列の長さです。配列をトラバースする必要があるのは1回だけです。
スペースの複雑さ:O(1)。複数の変数を格納するために必要なのは一定のスペースだけです。
ビッグスタースターのコメントを送るには、コメントセクションを参照してください2