この記事は、Datawhaleチームの調査計画の21番目のLeetCodeが選択したトピックグループTask10調査ノートです。
初心者の方は少し時間がかかり、多くの解決策は詳細に分析されておらず、将来改訂される可能性があります。ご容赦ください。
Datawhale学習ドキュメント:
https : //github.com/datawhalechina/team-learning-program/tree/master/LeetCodeTencent
121株式を売買するのに最適な時期
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
配列が与えられると、そのi番目の要素はi日目の特定の株式の価格です。
最大で1つのトランザクションしか完了できない場合(つまり、株式を1回売買する場合)、取得できる最大利益を計算するアルゴリズムを設計します。
注:株式を購入する前に売却することはできません。
例:
入力:[7,1,5,3,6,4]
出力:5
説明:2日目に購入(株価= 1)、5日目に販売(株価= 6)。最大利益= 6- 1 = 5。
販売価格は購入価格よりも高くする必要があるため、利益を7-1 = 6にすることはできません。同時に、購入する前に株式を販売することはできません。
入力:[7,6,4,3,1]
出力:0
説明:この場合、トランザクションは完了していないため、最大利益は0です。
アイデア
公式ソリューションでのトラバーサルのアイデア:
i日目に、その日に販売することにした場合、前日に購入するために歴史上最低のポイントを見つける必要があります。価格はminpriceで記録されます。
i日目に株式を売却する予定の場合、最大利益は[0、i-1]の間の最低点で購入し、maxprofitで記録する必要があります。
配列をトラバースして、売却時に得られるものを見つけます( i)毎日最大差、および過去の最低価格を更新すると、トラバーサルの終了時に利益の最大値が取得されます。
Pythonの実装
class Solution:
def maxProfit(self, prices: List[int]) -> int:
inf = int(1e9)
minprice = inf # 历史最低买入价格
maxprofit = 0 # 第i天卖出时能获得的最大利润
for i in prices:
maxprofit = max(i - minprice, maxprofit) # 遍历找到最大利润
minprice = min(i, minprice) # 更新历史最低价格
return maxprofit
122株式を売買するのに最適な時期Ⅱ
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii
配列が与えられると、その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です。
アイデア
在庫に関する質問のコレクションについては、在庫の問題に関する一連の一般的な解決策(再印刷および翻訳
)を参照してください。この質問の2つの一般的なアルゴリズム:動的計画法(より一般的)と欲張りアルゴリズム(やや特殊)。
欲張りアルゴリズム:局所最適解→グローバル最適ソリューション
- 「欲張りアルゴリズム」は、「動的計画法」および「バックトラッキング検索」アルゴリズムと同じです。1つのことを達成するために、それは段階的な決定です。
- 「欲張りアルゴリズム」は常に各ステップで最良の選択をします。私はこのように「最良」という2つの単語の意味を理解しています。「最良」
はトピックに応じて「最小」または「最大」を意味することがよくあります。 ;
動的計画法と比較して、欲張りアルゴリズムは前面(つまり、前の状態から転送する必要がない)または背面(後遺症なし、後者の選択は前の選択に影響を与えません)を見ないので、欲張りアルゴリズムの時間計算量は一般に線形であり、空間計算量は一定レベルです。
- この質問を「貪欲」にしているのは、「今日の株価-昨日の株価」について、①正、②000、③負の3つの結果が考えられるということです。欲張りアルゴリズムの決定は、正の数のみを追加することです。
著者:liweiwei1419
リンク:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/tan-xin-suan-fa-by-liweiwei1419-2/
Pythonの実装
(データクジラ学習ドキュメント)
class Solution:
def maxProfit(self, prices: List[int]) -> int:
earn = 0
for i in range(0, len(prices) - 1):
earn += max(prices[i + 1] - prices[i], 0)
return earn
124二分木の最大パス合計
ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/binary-tree-maximum-path-sum
パスは、ツリー内の任意のノードから始まり、親ノードと子ノードを接続し、任意のノードに到達するシーケンスとして定義されます。パスには少なくとも1つのノードが含まれますが、必ずしもルートノードを経由する必要はありません。
パスの合計は、パス内の各ノードの値の合計です。
二分木のルートノードルートを与え、その最大パス合計を返します。
例:
入力:ルート= [1,2,3]
出力:6
説明:最適なパスは2-> 1-> 3であり、パスの合計は2 + 1 + 3 = 6です。
入力:root = [-10,9,20、null、null、15,7]
出力:42
説明:最適なパスは15-> 20-> 7であり、パスの合計は15 + 20 + 7 = 42です。
促す:
ツリー内のノード数の範囲は[1、3 * 10 ^ 4]
-1000 <= Node.val <= 1000です。
アイデア
どのノードでも、最大合計パスにノードが含まれている場合、考えられる状況は2つだけです。
パス値とノードの値が大きい左右のサブツリーによって形成され、親ノードへのバックトラックが最大値を構成します。パス。
左右のサブツリーは最大パスにあり、このノードの値が最終的な最大パスを構成します。
公式ソリューションでの再帰的思考:
まず、二分木のノードの最大寄与値を計算する簡略化された関数maxGain(node)の実装を検討します。
具体的には、ノードをルートノードとしてサブツリー内のノードから始まるパスを見つけることです。これにより、パス上のノード値の合計が最大になります。
この関数の計算は次のとおりです。
- 空のノードの最大寄与値はゼロに等しくなります。
- 空でないノードの最大寄与値は、ノード値とその子ノードの最大寄与値の合計に等しくなります(リーフノードの場合、最大寄与値はノード値に等しくなります)。
最初にリーフノードの寄与値を検討し、次に非リーフノードを検討します
たとえば、次の二分木について考えてみます。
リーフノード9、15、および7の最大寄与値はそれぞれ9、15、および7です。
次に、非リーフノードの最大寄与値を計算します。ノード20の最大寄与値は20+ max(15,7)= 35に等しく、ノード-10の最大寄与値は-10 + max(9,35)= 25に等しくなります。
上記の計算プロセスは再帰的なプロセスであるため、各ノードの最大寄与値は、ルートノードで関数maxGainを呼び出すことによって取得できます。
二分木の最大パスと
二分木のノードの場合、ノードの最大パス合計は、ノードの値と、ノードの左右の子ノードの最大寄与値に依存します。子ノードの最大寄与値が正の場合、ノードの最大パス合計に含まれます。それ以外の場合は、ノードの最大パス合計としてカウントされません。グローバル変数maxSumを維持して最大パス合計を格納し、再帰プロセスでmaxSumの値を更新します。最終的なmaxSum値は、バイナリツリーの最大パス合計です。
Pythonの実装
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.maxSum = float("-inf")
def maxPathSum(self, root: TreeNode) -> int:
def maxGain(node):
if not node:
return 0
# 递归计算左右子节点的最大贡献值
# 只有在最大贡献值大于 0 时,才会选取对应子节点
leftGain = max(maxGain(node.left), 0)
rightGain = max(maxGain(node.right), 0)
# 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
priceNewpath = node.val + leftGain + rightGain
# 更新答案
self.maxSum = max(self.maxSum, priceNewpath)
# 返回节点的最大贡献值
return node.val + max(leftGain, rightGain)
maxGain(root)
return self.maxSum
# 作者:LeetCode-Solution
# 链接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-leetcode-/
# 来源:力扣(LeetCode)
# 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。