From 02a853993863281744179da54fc7dbbde0267faf Mon Sep 17 00:00:00 2001 From: nittoco <166355467+nittoco@users.noreply.github.com> Date: Mon, 3 Feb 2025 00:31:40 +0900 Subject: [PATCH] 122. Best Time To Sell and Buy Stock.md https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/ You are given an integer array prices where prices[i] is the price of a given stock on the ith day. On each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. However, you can buy it then immediately sell it on the same day. Find and return the maximum profit you can achieve. --- 122. Best Time To Sell and Buy Stock.md | 188 ++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 122. Best Time To Sell and Buy Stock.md 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 +```