着く時刻を前から比べて一本道でゴールに着く自転車の群れを数える

追い越しのできない一本道を走る自転車が、ゴールにいくつの群れで着くかを数えます。ゴールに近い順に並べ、前の群れより遅く着く自転車だけが新しい群れになる、と見抜く練習です。

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

問題

追い越しのできない一本道で、自転車が同じ向きに走っています。ゴールはスタートから target メートルの所です。i 番目の自転車は、いま position[i] メートルの所にいて、毎秒 speed[i] メートルで走ります。

速い自転車が前の自転車に追いつくと、追い越さずに後ろについて、前の自転車と同じ速さで一緒に走ります。一緒に走る自転車の組を 1 つの群れと呼びます (1 台だけでも群れです)。ゴールにいくつの群れが着くかを返す関数を書いてください。

  • ちょうどゴールの地点で追いついたときも、同じ群れとして数えます
  • position と speed の長さは同じで、1 以上 100000 以下です
  • position[i] は 0 以上 target 未満で、同じ位置の自転車はいません。target は 1 以上 1000000 以下です
  • speed[i] は 1 以上 1000000 以下です

入力と出力の例

例 1

ゴールに近い順に、14 の自転車は 6 秒、8 の自転車は 3 秒、6 の自転車は 14 秒、2 の自転車は 6 秒で着く速さです。8 の自転車は 14 の自転車に追いつき、2 の自転車は 6 の自転車に追いつきます。群れは 2 つです。

target = 20 position = [2, 8, 14, 6] speed = [3, 4, 1, 1]
2

例 2

1 台だけでも 1 つの群れです。

target = 10 position = [3] speed = [5]
1

例 3

どちらも 5 秒でゴールに着く速さです。後ろの自転車は、ちょうどゴールで追いつくので、同じ群れです。

target = 10 position = [0, 5] speed = [2, 1]
1

面接での聞かれ方

面接では、車の言葉で渡されることがよくあります。

  • 「同じ道を走る車が、目的地にいくつの集団で着くかを数えてください」
  • 「ちょうど目的地で追いついたら、同じ集団ですか?」と、境目を自分から確かめるかを見られます
  • 書き終えたあとに「着く時刻を小数で比べて大丈夫ですか?」と聞かれることもあります

追いつく時刻を自転車の組ごとに計算し始めると、組の数だけ手間がかかって迷います。「前にいる群れより先には着けない」に気づくと、1 本の並びをなめるだけになります。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「スタックとキュー」に、この型の要点を表とコードでまとめています。

スタックは後から入れた物を先に、キューは先に入れた物を先に取り出します。括弧の対応や、順番待ちの処理の形です。

main.py
def count_fleets(target: int, position: list[int], speed: list[int]) -> int:
    """
    Goal: 何を返すか

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

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

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


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

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