窓の左端に最安値を置いて 1 回の売り買いの利益を最大にする

日ごとの値段の並びから、1 回だけ買って、それより後の日に 1 回だけ売るときの、いちばん大きい利益を返します。窓の左端をそれまでの最安の日に置き、右端を 1 日ずつ進める練習です。

海外で定番の問題リスト 4 本のうち 4 本に入っています (Blind 75、NeetCode 150、Grind 75、LeetCode Top Interview 150)

問題

ある品物の、日ごとの値段の並び prices を受け取ります。並びの順が日の順です。どこか 1 日に 1 つ買い、それより後のどこか 1 日に売ります。売った値段から買った値段を引いた利益のうち、いちばん大きい値を返す関数を書いてください。

  • 買う日は売る日より前でなければなりません。同じ日に買って売ることはできません
  • どう売り買いしても利益が出ないときは、売り買いをしないことにして 0 を返します
  • prices の長さは 1 以上 100000 以下、値段はどれも 0 以上 10000 以下です

入力と出力の例

例 1

値段 2 の日に買い、その次の値段 7 の日に売ると、5 の利益です。

prices = [8, 3, 6, 2, 7, 4]
5

例 2

値段が下がり続けるなら、売り買いしないのがいちばんです。

prices = [9, 7, 4, 1]
0

例 3

いちばん安い日がいちばん高い日より後にあると、その 2 日では売り買いできません。

prices = [2, 10, 1, 5]
8

面接での聞かれ方

面接では、株の値動きの場面として短く聞かれることが多いです。

  • 「株価の配列があります。1 回だけ買って売るとき、最大の利益はいくらですか?」
  • 「最安値で買って最高値で売ればよいのでは?」と、わざと落とし穴へ誘う形で聞かれることもあります
  • 書き終えたあとに「何回でも売り買いできたらどうしますか?」と、条件を変えた続きが出ることがあります

最初に、買うのは売るより前であること、利益が出ないときに何を返すかを確かめてから書き始めます。

ヒント

まだ開いていません

付箋は 3 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3答えに近い

アルゴリズムのチートシートの「配列と文字列」に、この型の要点を表とコードでまとめています。

配列と文字列の問題は、全部の組を調べると手間が大きくなる所を、窓や左右の添字で減らす形が多いです。

main.py
def max_profit(prices: list[int]) -> int:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(max_profit([8, 3, 6, 2, 7, 4]))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します