スライディングウィンドウで同じ文字の無い最長の部分を探す

文字列の​中で、​同じ​文字が​ 2 回出て​こない​続いた​部分の​うち、​いちばん長い物の​長さを​返します。​左右の​端を​持つ窓を​伸ばし、​重なりが​出たら​左の​端を​飛ばして​縮める​練習です。

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

問題

文字列 s を受け取ります。s の中の続いた部分 (飛ばさずに切り出した部分) で、同じ文字が 2 回以上出てこない物のうち、いちばん長い物の長さを返す関数を書いてください。

  • 「続いた部分」なので、文字を飛ばして拾った物は数えません。"abcb" から a、c、b を飛ばして拾った "acb" は使えません
  • 大文字と小文字は別の文字です。空白や記号も 1 つの文字として数えます
  • s は空のこともあります。そのときは 0 を返します
  • s の長さは 0 以上 50000 以下で、英字、数字、記号、空白 (ASCII の文字) だけでできています

入力と出力の例

例 1

"toky" と "kyot" が長さ 4 で、同じ文字がありません。5 文字にすると、どこを取っても o か t が 2 回出てきます。

入力

s = "tokyoto"

出力

4

例 2

右の a は、左の a と重なります。ただし、その前に b の重なりで左の端はもう右へ進んでいるので、左の a は窓の外です。答えは "ab" か "ba" の 2 です。

入力

s = "abba"

出力

2

例 3

空の文字列です。

入力

s = ""

出力

0

面接での聞かれ方

スライディングウィンドウの問題の中で、いちばんよく出る 1 問です。問題文はとても短く渡されます。

  • 「文字列の中で、同じ文字を含まない最長の部分文字列の長さを返してください」
  • 最初に条件を確かめると評価が上がります。「部分文字列は続いた部分ですか、飛ばしてもよいですか?」「空の文字列は来ますか?」「文字の種類は何ですか、英小文字だけですか?」の 3 つは聞いておきます
  • 書き終えたあとに、次のような続きがよく来ます
    • 「長さではなく、その部分そのものを返してください」 (左の端と長さを覚えておけば済みます)
    • 「同じ文字を k 回まで許すなら?」「違う文字が k 種類までなら?」 (窓の中の数を数える辞書に替えます)
    • 「使う記憶を文字の種類で言うと?」 (記憶は O(min(n, m))、m は文字の種類の数、と答えます)
  • 「全部試す書き方から、どうやって速くしましたか?」と、考えの筋を順に聞かれることもあります

ミドルの問題なので、窓を正しく縮められることに加えて、"abba" のような左の端が戻ってしまう場合を自分で見つけられるかが見られます。

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

main.py
def longest_unique_substring(s):
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(longest_unique_substring("tokyoto"))

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