Conversation
| 計算量: | ||
| - 時間 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) は上限ではない |
There was a problem hiding this comment.
一般項 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を含意している変数名がある |
There was a problem hiding this comment.
https://en.cppreference.com/w/cpp/container/vector/end

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.
There was a problem hiding this comment.
inclusiveと下限、exclusiveと上界がごっちゃになっていました。
参考資料ありがとうございます。
| seen_chars = set() | ||
| base_index = 0 | ||
| right = 0 | ||
| while base_index < len(s): |
There was a problem hiding this comment.
base_indexが+1ずつ動いているので、for loopの方がわかりやすいです。
There was a problem hiding this comment.
自明な書き換えのはずだと思うのですが気づけませんでした。rangeで書き直してみます。
| base_index = 0 | ||
| right = 0 | ||
| while base_index < len(s): | ||
| while right < len(s) and s[right] not in seen_chars: |
There was a problem hiding this comment.
このrightがexclusiveなのは変数名から自明ではないですよね。
There was a problem hiding this comment.
whileからforに書き直せばこちらも明示できると思いました。インデックスが動く範囲を読りやすい変数名、制御構造にすることを意識します。
| def lengthOfLongestSubstring(self, s: str) -> int: | ||
| # 4'15 -> 5'25 -> 4'01 | ||
| longest_length = 0 | ||
| seen_chars = set() |
There was a problem hiding this comment.
sliding windowなので、window_charsなどと表現することもできます。seen_charsだと今まで見た全ての文字みたいな印象ですが、実際には[left, right)に含まれる文字ですよね。
There was a problem hiding this comment.
window_chars は全く思いつきませんでした。とても明確でわかりやすいと感じたので、類似の問題では window_x を使えないかまず考えるようにします。
window_chars と類似の変数名として、substring_chars, chars_in_substring なども使えそうだと思いました。
| 注目している部分文字列が含む文字をsetで記憶 | ||
|
|
||
| 計算量: | ||
| - 時間 O(n) left, rightともにsの末尾近くまで進むとき最悪でO(2n)、すべての文字列が異なるとき最善。 |
There was a problem hiding this comment.
定数倍を気にするシチュエーションでは、多項式中の最も強い項以外でも定数倍を気にする必要がありそうなので、O記法を避けるようにします。
| char_count_map[char] += 1 | ||
| return char_count_map | ||
|
|
||
| def nums_appear_once(self, nums: List[int]): |
There was a problem hiding this comment.
コピペのミスで判定関数が消失 & インデントが崩れていました。ご指摘ありがとうございます。PRを出す前に確認漏れがないようにします。
| char_count_map = defaultdict(int) | ||
| for char in s: | ||
| char_count_map[char] += 1 | ||
| return char_count_map |
There was a problem hiding this comment.
ご存知かも知れませんが、一応貼っておきます。
https://docs.python.org/3/library/collections.html#collections.Counter
There was a problem hiding this comment.
ありがとうございます。
以下、ドキュメントと実装を読んで気づいたことのメモです。
Counter クラスは key, value の value として負の数を許している。
- クラス名からは意外だったのですが、subtract()メソッド の結果が負の数にもなりうるというので納得しました。
- なお、Counterクラスの命名については次の議論がありました。Add collections.counts() python/cpython#44815 (comment))
Counter.most_common() は内部で heaqp.nlargest() を呼んでいる。
- 練習会でよく解かれている Top K Frequent Elements ぽかったので調べてみたのですが、discord で既出の話でしたね。
- https://discord.com/channels/1084280443945353267/1227102763222171648/1239500226851635221
- https://github.com/YukiMichishita/LeetCode/pull/3/files#r1609242085
No description provided.