Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# 3. Longest Substring Without Repeating Characters
## STEP1
- 何も見ずに解いてみる
- 始点と終点を進めていく過程で文字のカウントをしておく。重複しない限り終点を先に進めて重複した時点で長さを取得。
```python
import collections


class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
longest_length = 0

end_index = 0
characters = collections.defaultdict(int)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

step 1の解答にコメントを残すのは無粋かもしれませんが、このdefaultdictで文字とそのカウントが対応していることを読み取るのに少し時間がかかりました。既に意識されていることと思いますが、char_to_countにするか、0か1のフラグを保持していることを伝えられるといいな、と思いました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そちらの方がわかりやすいですね。コメントありがとうございます。

for start_index in range(len(s)):
while end_index < len(s) and characters[s[end_index]] == 0:
characters[s[end_index]] = 1
end_index += 1
longest_length = max(longest_length, end_index - start_index)

characters[s[start_index]] -= 1
return longest_length
```

## STEP2
### プルリクやドキュメントを参照
- https://github.com/olsen-blue/Arai60/pull/49/files
- 重複しないように index を進めているので、考慮している範囲の文字の出現回数は 0, 1 であり、set で管理することで十分。
- right を順に進めることもできる。重複した文字が出た際の挙動はこちらの方がわかりやすい。
right を進める書き方
```python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
longest_length = 0
left_index = 0
characters = set()
for right_index in range(len(s)):
while s[right_index] in characters:
characters.remove(s[left_index])
left_index += 1
characters.add(s[right_index])
longest_length = max(longest_length, right_index - left_index + 1)
return longest_length
```
- https://github.com/hayashi-ay/leetcode/pull/47/files
- 見たことがある文字の index を管理することで、範囲の更新が効率的になる。
```python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
longest_length = 0
left_index = 0
letter_to_index = {}
for right_index in range(len(s)):
if s[right_index] in letter_to_index:
left_index = max(left_index, letter_to_index[s[right_index]] + 1)
letter_to_index[s[right_index]] = right_index
longest_length = max(longest_length, right_index - left_index + 1)
return longest_length
```
- https://github.com/olsen-blue/Arai60/pull/49/files#r2005295464
- 条件分岐せずに書く方法。読む難易度は若干上がるので自分では書かない気がします。ただ、現状は get 使う方法が選択肢に入っていないので良くない。
left_index = max(left_index, letter_to_index.get(s[right_index], -1) + 1)

## STEP3
### 3回ミスなく書く
set で重複管理する方法がファーストチョイスと思いました。
```python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
longest_length = 0
left = 0
letters_in_window = set()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いい変数名ですね。

for right in range(len(s)):
while s[right] in letters_in_window:
letters_in_window.remove(s[left])
left += 1
letters_in_window.add(s[right])
longest_length =max(longest_length, right - left + 1)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: =の後に一つスペースを開けるのが一般的かと思います。

return longest_length
```

2分,2分,1分で3回Accept
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いいと思います。
letters_in_windowいいですね