Skip to content

3 https://leetcode.com/problems/longest-substring-without-repeating-characters/description/#3

Merged
sakzk merged 9 commits intomainfrom
3
Jun 14, 2024
Merged

3 https://leetcode.com/problems/longest-substring-without-repeating-characters/description/#3
sakzk merged 9 commits intomainfrom
3

Conversation

@sakzk
Copy link
Copy Markdown
Owner

@sakzk sakzk commented May 5, 2024

No description provided.

計算量:
- 時間 O(n^3) 二重ループの中で配列の走査を2回呼んでいる O(n^2 * (n + n))。TLE
- 空間 O(n^3) O(n)のdictをn^2個構築している
- 入力の文字列長をnとして、substringの文字数の総和は、1文字がn個、2文字がn-1個、3文字がn-2個、、、n文字が1個。長い文字列ほど少ないので O(n^3) は上限ではない
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

あ、これは O(n^3) ですね。

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.

一般項 a_n = k*n - (k-1)*k の数列のk=1からnまでの和で、一番強い項が n^3ですね。雰囲気で見積もっていました。
辞書のメモリ使用に関連して、hashの衝突を避けるために要素数に応じて余分に領域を確保している、も聞かれることがあるのかなと思いました。

# 参考
- https://github.com/thonda28/leetcode/pull/6/files#diff-6b92fcf16b9cd27d1d2d7ff3daeb4a7f48fb0a4fd64c5c68c2a58ae7af4a1837
- dictの命名は `x_to_y` もよさそう
- inclusive, exclusiveを含意している変数名がある
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

https://en.cppreference.com/w/cpp/container/vector/end
image

https://en.wikipedia.org/wiki/Upper_and_lower_bounds

In mathematics, particularly in order theory, an upper bound or majorant[1] of a subset S of some preordered set (K, ≤) is an element of K that is greater than or equal to every element of S.

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.

inclusiveと下限、exclusiveと上界がごっちゃになっていました。
参考資料ありがとうございます。

seen_chars = set()
base_index = 0
right = 0
while base_index < len(s):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

base_indexが+1ずつ動いているので、for loopの方がわかりやすいです。

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.

自明な書き換えのはずだと思うのですが気づけませんでした。rangeで書き直してみます。

base_index = 0
right = 0
while base_index < len(s):
while right < len(s) and s[right] not in seen_chars:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

このrightがexclusiveなのは変数名から自明ではないですよね。

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.

whileからforに書き直せばこちらも明示できると思いました。インデックスが動く範囲を読りやすい変数名、制御構造にすることを意識します。

def lengthOfLongestSubstring(self, s: str) -> int:
# 4'15 -> 5'25 -> 4'01
longest_length = 0
seen_chars = 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.

sliding windowなので、window_charsなどと表現することもできます。seen_charsだと今まで見た全ての文字みたいな印象ですが、実際には[left, right)に含まれる文字ですよね。

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.

window_chars は全く思いつきませんでした。とても明確でわかりやすいと感じたので、類似の問題では window_x を使えないかまず考えるようにします。
window_chars と類似の変数名として、substring_chars, chars_in_substring なども使えそうだと思いました。

注目している部分文字列が含む文字をsetで記憶

計算量:
- 時間 O(n) left, rightともにsの末尾近くまで進むとき最悪でO(2n)、すべての文字列が異なるとき最善。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

定数倍は普通O記法の中に書かないかもしれません。

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.

定数倍を気にするシチュエーションでは、多項式中の最も強い項以外でも定数倍を気にする必要がありそうなので、O記法を避けるようにします。

char_count_map[char] += 1
return char_count_map

def nums_appear_once(self, nums: List[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.

この関数使ってないです。

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.

コピペのミスで判定関数が消失 & インデントが崩れていました。ご指摘ありがとうございます。PRを出す前に確認漏れがないようにします。

@sakzk sakzk changed the title https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ 3 https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ May 10, 2024
char_count_map = defaultdict(int)
for char in s:
char_count_map[char] += 1
return char_count_map
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ご存知かも知れませんが、一応貼っておきます。
https://docs.python.org/3/library/collections.html#collections.Counter

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.

ありがとうございます。

以下、ドキュメントと実装を読んで気づいたことのメモです。

Counter クラスは key, value の value として負の数を許している。

  • クラス名からは意外だったのですが、subtract()メソッド の結果が負の数にもなりうるというので納得しました。
  • なお、Counterクラスの命名については次の議論がありました。Add collections.counts() python/cpython#44815 (comment))

Counter.most_common() は内部で heaqp.nlargest() を呼んでいる。

@sakzk sakzk deleted the 3 branch August 5, 2025 02:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants