ツーポインタで並んだ壁のあいだにたまる雨水の量を求める

幅 1 の壁の高さの並びから、雨が降ったあと壁のあいだにたまる水の量を求めます。両端から 2 本の指を寄せ、低い側の水の高さはもう決まっていると見抜く、ツーポインタの練習です。

海外で定番の問題リスト 4 本には入っていません

問題

庭に、幅 1 の壁が横に隙間なく並んでいます。左から順の壁の高さを、0 以上の整数の並び heights で受け取ります。雨が降ったあと、壁のあいだにたまる水の量 (幅 1、高さ 1 を 1 と数えた合計) を返す関数を書いてください。

  • 左端より左と、右端より右には壁が無く、水はそこから流れ出ます
  • 高さ 0 の所は地面で、水がたまれば地面の上にたまります
  • heights の長さは 0 以上 20000 以下で、値は 0 以上 100000 以下です

入力と出力の例

例 1

左の高さ 3 と右の高さ 4 の壁にはさまれ、水は高さ 3 までたまります。3 つの所に、3、1、3 の水がたまり、合計 7 です。

heights = [3, 0, 2, 0, 4]
7

例 2

まん中がいちばん高い山の形です。どこも片側が低く、水は流れ出るので、たまりません。

heights = [1, 2, 3, 2, 1]
0

例 3

左の 4 より右の 3 が低いので、水は高さ 3 までです。左から 2、2、3、1 の水がたまり、合計 8 です。

heights = [4, 1, 1, 0, 2, 3]
8

面接での聞かれ方

面接では、棒グラフの絵を見せて聞かれることがよくあります。

  • 「この棒のあいだに、雨水はどれだけたまりますか?」
  • 「O(n) の時間で、記憶を O(1) にできますか?」と、段を踏んで詰められます
  • 「両端より外に水は流れますか?」と、決まりを自分から確かめるかも見られます

難しい問いとして知られていますが、1 つの所にたまる水の高さを先に式にすると、あとは計算の順を工夫するだけになります。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

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

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

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

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

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

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


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

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