From d3c8e0b661646ad2d84ddc081fbb5311dc0ffec9 Mon Sep 17 00:00:00 2001 From: fuga-98 <134851906+fuga-98@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:52:15 +0900 Subject: [PATCH] Create 122. Best Time to Buy and Sell Stock II.md https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/ --- 122. Best Time to Buy and Sell Stock II.md | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 122. Best Time to Buy and Sell Stock II.md diff --git a/122. Best Time to Buy and Sell Stock II.md b/122. Best Time to Buy and Sell Stock II.md new file mode 100644 index 0000000..01d21e2 --- /dev/null +++ b/122. Best Time to Buy and Sell Stock II.md @@ -0,0 +1,154 @@ +# 進め方 + +Step1 : 問題を解く。 + +Step2 : 他の人のPRを参照し、コメントする。 + +Step3 : 3回続けてエラーが出ないように書く。ドキュメントを参照する。 + +# 実践 + +## Step1 + +### 思考ログ + +テストケース + +7,1,5,6,3,4 + +None + +1,3,5 + +1 + +多分いくつかやり方がある。 + +①明日の金額が値下がりするなら売る。明日が値上がりなら売らない。(デイトレーダーっぽい) + +→ 前日と比べて差が0より大きいなら利益に可算する + +時間O(N) 空間O(1) + +```python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + assert isinstance(prices, list) + if len(prices) <= 1: + return 0 + total_profit = 0 + for i in range(1, len(prices)): + total_profit += max(0, prices[i] - prices[i-1]) + return total_profit +``` + +②山で売って、谷で買う。 + +株の取引なら手数料があることもあると思うので、なるべく売買の回数を減らす方法で。 + +↓動きません。 + +初手と終わりが難しい + +```python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + assert isinstance(prices, list) + if len(prices) <= 1: + return 0 + is_upward = False + result = 0 + holding = prices[0] + for i in range(1, len(prices) - 1): + print(holding) + diff_next = prices[i+1] - prices[i] + # 谷 + if not is_upward and diff_next > 0: + is_upward = True + holding = prices[i] + continue + # 山 + if is_upward and diff_next < 0: + is_upward = False + result += prices[i] - holding + result += max(0, prices[-1] - holding) + return result + +``` + +詰まったのでAIに直してもらった。Whileのほうが分かりやすい。 + +```python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + assert isinstance(prices, list): + if len(prices) <= 1: + return 0 + total_profit = 0 + i = 0 + num_prices = len(prices) + while i < num_prices - 1: + # 1. 谷 (Valley) を見つける + while i < num_prices - 1 and prices[i+1] <= prices[i]: + i += 1 + bottom = prices[i] + # 2. 山 (Peak) を見つける + while i < n - 1 and prices[i+1] >= prices[i]: + i += 1 + peak = prices[i] + total_profit += peak - bottom + return total_profit +``` + +## Step2 + +### 同じ問題を解いた人のプルリクを見る + +https://github.com/olsen-blue/Arai60/pull/38 + +- Step3は読みやすい。 + +https://github.com/nittoco/leetcode/pull/44 + +- 関数でindexを受け取ると変数名が長くなるが、i = start_index としてシンプルに見えるようにできる + +https://github.com/hroc135/leetcode/pull/36 + +- 同時に更新したほうが自然。 +- https://github.com/hroc135/leetcode/pull/36#discussion_r1913384463 + +https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0 + +毎日できることは、株を持っているか、お金を持っているかの2択なので、未来が見える人になったとして、どちらがいいかを考えればいいのです。 + +## Step3 + +### 3回連続で再現できるようになる + +改めて書いてみるとolsen-blueさんの関数名は上手だと感じる。 + +最小の取引回数で + +```python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + assert isinstance(prices, list) + num_prices = len(prices) + if num_prices <= 1: + return 0 + profit = 0 + i = 0 + while i < num_prices - 1: + # 底を見つける + while i < num_prices - 1 and prices[i] >= prices[i+1]: + i += 1 + if i == num_prices - 1: + break + profit -= prices[i] + # 頂点を見つける + while i < num_prices - 1 and prices[i] <= prices[i+1]: + i += 1 + profit += prices[i] + return profit +``` +