diff --git a/122. Best Time To Sell and Buy Stock.md b/122. Best Time To Sell and Buy Stock.md new file mode 100644 index 0000000..a389848 --- /dev/null +++ b/122. Best Time To Sell and Buy Stock.md @@ -0,0 +1,188 @@ +### Step1 + +- 頭の中でグラフを思い浮かべた。今より前の時点のやつを売買することができる(ズル)ので、今の値と比較してどうかで決めれる +- is_havingのようなフラグ変数は管理しづらくなるだろうか。1個くらいならOK? + +```python +python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + profit = 0 + is_having = False + prev_price = None + for price in prices: + if prev_price is None: + pass + elif is_having and prev_price > price: + profit += prev_price + is_having = False + elif not is_having and prev_price < price: + profit -= prev_price + is_having = True + prev_price = price + if is_having: + profit += prev_price + is_having = False + return profit +``` + +- テストケースを考える(実は今まであんまりやってなかった😅) + - [] + - [5] + - [-4] (株価がマイナスはなさそう) + - [0] + - [4, 5] + - [5, 4] + - [3, 3] + - [4, 5, 4] + - [5, 4, 5] + - [4, 5, 5] + - [4, 4, 5] + - [5, 4, 4] + - [5, 5, 4] + - [0, 0, 0, 0, 0, 0, 0, 0,,,,] + - [2, 2, 2, 2,,,,,,,,] + - [4, 5, 4, 5, 4, 5, 4, 5,,,,,,,] + - [5, 4, 5, 4, 5, 4, 5, 4,,,,] + - [4, 5, 6, 5, 4, 5, 6, 5, 4,,,,,] + - [6, 5, 4, 5, 6, 5, 4, 5, 6,,,,,] + - [1, 2, 3, 4, 5, 6,,,,] + - [100, 99, 98, 97, ,,,,,,] +- くらいかな。うーん。 + + + +https://discord.com/channels/1084280443945353267/1210494002277908491/1210793843260133477 + +https://github.com/fhiyo/leetcode/pull/39/files + +[https://github.com/TORUS0818/leetcode/pull/40](https://github.com/TORUS0818/leetcode/pull/40#discussion_r1875358734) + +- 関数を定める方法、DPでやる方法などがある + - 関数を定める方法で書いてみる + - find_next_peakとfind_next_bottomはよく似て関数だが、ここを無理やり共通化しようとするのは流石にややこしい? + +```python +class Solution: + def find_next_peak(self, start_index: int, nums: List[int])-> Tuple[int, int]: + assert start_index < len(nums) + i = start_index + while i + 1 < len(nums) and nums[i] <= nums[i + 1]: + i += 1 + return i, nums[i] + + def find_next_bottom(self, start_index: int, nums: List[int])-> Tuple[int, int]: + assert start_index < len(nums) + i = start_index + while i + 1 < len(nums) and nums[i] >= nums[i + 1]: + i += 1 + return i, nums[i] + + def maxProfit(self, prices: List[int]) -> int: + assert(len(prices) > 0) + profit = 0 + i = 0 + bought_price = prices[0] + while i < len(prices) - 1: + peak_index, peak_price = self.find_next_peak(i, prices) + profit += peak_price - bought_price + bottom_index, bottom_price = self.find_next_bottom(peak_index, prices) + i = bottom_index + bought_price = bottom_price + return profit +``` + +-  https://github.com/hayashi-ay/leetcode/pull/56 + +- find_next_bottom関数の返り値、indexだけの方がシンプルで良いだろうか、でも値もあった方が便利そうでむずい +- https://github.com/Ryotaro25/leetcode_first60/pull/42 + - price[i + 1] - prices[i] を変数に置いた方がいいのはなるほど +- 持ってる時、持ってない時で出す + +```python + +class Solution: + def maxProfit(self, prices: List[int]) -> int: + assert(len(prices) > 0) + profit_having_stock_prev = -prices[0] + profit_not_having_stock_prev = 0 + for i in range(1, len(prices)): + profit_having_stock = max(profit_having_stock_prev, profit_not_having_stock_prev - prices[i]) + profit_not_having_stock = max(profit_not_having_stock_prev, profit_having_stock_prev + prices[i]) + profit_having_stock_prev = profit_having_stock + profit_not_having_stock_prev = profit_not_having_stock + return max(profit_having_stock_prev, profit_not_having_stock_prev) + ``` + +``` + +- https://github.com/seal-azarashi/leetcode/pull/36 + - 以下のコードでも通るっぽい。簡潔ではあるが、max(profit_not_having_stock, profit_having_stock + prices[i]) の時だけprofit_having_stockが実は同時点で、ただ前の行で更新されているならば-prices[i]と+prices[i]で打ち消しあって、前時点のprofit_not_having_stockに結果的になる、という推理が必要? + +```python + +class Solution: + def maxProfit(self, prices: List[int]) -> int: + assert(len(prices) > 0) + profit_having_stock= -prices[0] + profit_not_having_stock = 0 + for i in range(1, len(prices)): + profit_having_stock = max(profit_having_stock, profit_not_having_stock - prices[i]) + profit_not_having_stock = max(profit_not_having_stock, profit_having_stock + prices[i]) + return max(profit_having_stock, profit_not_having_stock) +``` + +- https://github.com/goto-untrapped/Arai60/pull/59 + - peakとbottomを交互にループするのは、最初にbottomをやった方が綺麗そう?気づかなかった。 + +```python +python +class Solution: + def find_next_peak(self, start_index: int, nums: List[int])-> Tuple[int, int]: + assert start_index < len(nums) + i = start_index + while i + 1 < len(nums) and nums[i] <= nums[i + 1]: + i += 1 + return i, nums[i] + + def find_next_bottom(self, start_index: int, nums: List[int])-> Tuple[int, int]: + assert start_index < len(nums) + i = start_index + while i + 1 < len(nums) and nums[i] >= nums[i + 1]: + i += 1 + return i, nums[i] + + def maxProfit(self, prices: List[int]) -> int: + assert(len(prices) > 0) + profit = 0 + i = 0 + while i + 1 < len(prices): + bottom_i, bottom_price = self.find_next_bottom(i, prices) + peak_i, peak_price = self.find_next_peak(bottom_i, prices) + profit += peak_price - bottom_price + i = peak_i + return profit +``` + +- https://github.com/sakupan102/arai60-practice/pull/39 + +https://github.com/shining-ai/leetcode/pull/38 + +https://github.com/hroc135/leetcode/pull/36/files   + +- profit_having_stockとprofit_not_having_stockを同時に更新するというてもあるか。ただ1行が長くなって見にくくなりそう。 + +## Step3 + +これが自然かな + +```python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + profit = 0 + for i in range(len(prices) - 1): + diff = prices[i + 1] - prices[i] + if diff > 0: + profit += diff + return profit +```