【海外エンジニア転職 Coding Interview鍛錬】LeetCode121. Best Time to Buy and Sell Stock
こんにちは脳筋ニシキです!
今回はこちらで紹介したLeetCode75選(Blind75)から1問(easy)選んで解いていきたいと思います!
atsashimipy.hatenablog.com

今日解いていくのはこちらの問題
やること
"prices"として渡されたとある銘柄の株の値動き表した配列から、一度づつの売買で最高益を返す。
prices[i] は、この銘柄のi日目の価格
条件
1 <= prices.length <= 10^5
0 <= prices[i] <= 10^4
例
Input: prices = [7,1,5,3,6,4]
Output: 5
この条件下で最高益は
価格が1の時に買い、6の時に売って得られる5。
カテゴリ
Arrays
考え方
とりあえず現実世界と同じで一番安い時に買って、一番高い時に売る!
ここで大事なのは買った時の値段と売った時の値段、そしてその差のから生まれる利益。
利益 = 売値 - 買値
0日目からN日目までの利益の動きをチェックしつつ、できるだけO(N)で解いていきたい。
上の例を見て考えてみる。
その日時点での一番の買い時(最安値)と最高益に注意しながら
0日目から見ていく。
prices = [7,1,5,3,6,4]
0日目:価格7 初日で比べる対象がないので、最安値=7 最高益=0
1日目:価格1 前日の7より安いので、この時点での最安値=1に更新 最高益=0 のまま
2日目:価格5 利益は5−1で4で現時点での最高益 最安値=1のままで 最高益=4に更新
3日目:価格3 利益は3−1で2出ているが最高益でないので 最安値=1 最高益=4のまま
4日目:価格6 利益は6−1で5最高益を更新 最安値=1のままで、最高益=5に更新
5日目:価格4 利益は4−1で3 最安値=1 最高益=5のまま
こうして最高益 = 5が確定される。
ではこの考え方をもとに
早速codeしていく!
class Solution: def maxProfit(self, prices: List[int]) -> int:
まず特殊ケースを対処。
class Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0
思いつくのは与えられた配列の長さが1の時。
つまり0日目で終わってる時、これは価格がどうあろうと最高益は0。というか取引できない。
問題文にも利益が出ないときは0を返せと書いてある。
If you cannot achieve any profit, return 0
次に買う日&売る日の初期値(2ポインター)と現時点での利益を設定する。
買う日と売る日は別々でないといけないので、
買う日を0日目
売る日を1日目
最高益を0
とする。
class Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0 buy = 0 sell = 1 profit = 0
そして、この2つのポインターを上で考えたように
while loop で1日ずつ価格の変動と現在の利益(売値–買値)をチェックしていく。
class Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0 buy = 0 sell = 1 profit = 0 while sell < len(prices): curr_profit = (prices[sell] - prices[buy])
もし現在の時点で利益がマイナスだった場合。
それはつまり最安値が更新されたということ。
なのでこの価格で買うのが現状ベスト。
ということで”buy”ポインターをこの日に移動。
class Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0 buy = 0 sell = 1 profit = 0 while sell < len(prices): curr_profit = (prices[sell] - prices[buy]) if curr_profit <= 0: buy = sell
そして次は
もし現在の時点で利益がプラスだった場合。
それはつまり最高益が更新された可能性があるということ。
なので今までの最高益の値と今回の利益を比べて、大きい方を新たな最高益と再設定。
lass Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0 buy = 0 sell = 1 profit = 0 while sell < len(prices): curr_profit = (prices[sell] - prices[buy]) if curr_profit <= 0: buy = sell else: profit = max(profit, curr_profit)
そして1日の価格をチェックし終えたら次の日を調べるため”sell”ポインターを一つ次に進めます。
lass Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0 buy = 0 sell = 1 profit = 0 while sell < len(prices): curr_profit = (prices[sell] - prices[buy]) if curr_profit <= 0: buy = sell else: profit = max(profit, curr_profit) sell += 1
とこんな感じで書いていくと、あとは勝手にpythonさんがやってくれるので、
while loop が終わったらあとはprofitを返すだけ。
そうするとこんな感じになります。
解答例
class Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) == 1: return 0 buy = 0 sell = 1 profit = 0 while sell < len(prices): curr_profit = (prices[sell] - prices[buy]) if curr_profit <= 0: buy = sell else: profit = max(profit, curr_profit) sell += 1 return profit
Complexity Analysis
Time complexity: O(n)
与えられた長さnの配列を一巡するだけ
Space complexity: O(1)
3つの変数(buy, sell, profit)

自分の考えを文字に起こすと理解が深まっていいな!
ただ、伝わりづらい部分も多々あると思うので、ご意見、感想、アドバイスお待ちしています!
それではまた次のLeetCodeの問題でお会いしましょう!