貪欲で輪を 1 周できる出発点を求める

貪欲法問題 165

輪になった配送の道で、電気自動車が 1 周できる出発の充電所の番号を返す。電池が足りなくなったら、その次の充電所から出発し直すと決めるだけで、前から 1 回なめて答えが出ます。

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

問題

輪になった配送の道に、充電所が番号 0 から順に並んでいます。充電所 i では電気を charge[i] だけ足せ、充電所 i から次の充電所 (最後の充電所の次は 0 番) へ進むには電気を cost[i] だけ使います。電池が空の電気自動車で、どこか 1 つの充電所から出発し、番号の増える向きに 1 周して出発した充電所へ戻りたいとします。1 周できる出発の充電所の番号を返し、どこから出ても 1 周できなければ -1 を返す関数を書いてください。

  • 1 周できる出発の充電所があるなら、それは 1 つだけになるような入力だけが渡されます
  • 進む途中で電気がちょうど 0 になるのはかまいませんが、負になる所へは進めません
  • 電池には上限がなく、足した電気は全部たまります
  • charge と cost の長さは同じで 1 以上 100000 以下、値はどれも 0 以上 10000 以下です

入力と出力の例

例 1

充電所 2 から出ると、電気は 5 - 1 で 4、2 - 3 を足して 3、3 - 2 を足して 4、1 - 4 を足して 1 と、負にならずに戻れます。ほかの充電所からでは途中で足りなくなります。

charge = [3, 1, 5, 2] cost = [2, 4, 1, 3]
2

例 2

足せる電気の合計は 6、使う電気の合計は 7 なので、どこから出ても 1 周できません。

charge = [2, 2, 2] cost = [3, 2, 2]
-1

例 3

充電所が 1 つだけで、足した 4 をちょうど使い切って戻れます。

charge = [4] cost = [4]
0

面接での聞かれ方

面接では、ガソリンスタンドの話として出されることが多いです。

  • 「輪になった道にスタンドがあります。1 周できる出発点を答えてください」
  • 最初に全部の出発点を試す書き方を話し、「O(n) にできますか」と聞かれる流れがよくあります
  • 書き終えたあとに「なぜ足りなくなった所の次から出直してよいのですか」と、理由を聞かれることもあります

答えが複数あるときにどれを返すかを、書く前に確かめておきます。この問題では、答えは多くとも 1 つと決めています。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3答えに近い

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

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

main.py
def start_station(charge: list[int], cost: list[int]) -> int:
    """
    Goal: 何を返すか

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

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

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


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

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