-
Notifications
You must be signed in to change notification settings - Fork 0
Solved Arai60/392. Is Subsequence #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| ## Step 1. Initial Solution | ||
|
|
||
| - 最初に思い付いたのは subsequence の文字列を一つずつ見て行って、元文字列を前から線形に探索していく方法 | ||
| - 特に整序されているわけではないのでこの順番で見ていくのが良さそう | ||
| - 毎度文字列のコピーをするのは避けたいのでindexを動かしていく | ||
| - indexを動かしながら見つからない時の処理をする | ||
| - 本当はfind関数の方が最適化されていて速そうだが引数の順番とかを思い出せなかったのでfor文で実装 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isSubsequence(self, s: str, t: str) -> bool: | ||
| last_char_index = 0 | ||
| char_index = 0 | ||
| for c in s: | ||
| for i in range(last_char_index, len(t)): | ||
| if c == t[i]: | ||
| char_index = i + 1 | ||
| break | ||
| if last_char_index == char_index: | ||
| return False | ||
| last_char_index = char_index | ||
| return True | ||
| ``` | ||
|
|
||
| - str.find(ch, index_from)のような形だった気がすると思って実装したら行けた | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isSubsequence(self, s: str, t: str) -> bool: | ||
| char_index = 0 | ||
| for c in s: | ||
| char_index = t.find(c, char_index) + 1 | ||
| if char_index == 0: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. find() から -1 が返ってきたときに、 t.find(c, char_index) + 1 が 0 になるから return False するというのは、ややパズルに感じました。 char_index = t.find(c, char_inde)
if char_index == -1:
return False
char_index += 1のほうが分かりやすいと思います。 |
||
| return False | ||
| return True | ||
| ``` | ||
|
|
||
| ### Complexity Analysis | ||
|
|
||
| - 時間計算量:O(n) | ||
| - n: tの長さ (=10^4)より10^8 Step/sならk*0.1ms | ||
| - 空間計算量:O(1) | ||
|
|
||
| ## Step 2. Alternatives | ||
|
|
||
| - Follow upの「もし沢山の subsequences を確認するならどうするか」という点については、tから辞書を作って参照しながら進める方が速そう | ||
| - ただ、高々26分割して探せるだけなので大きな高速化には至らないか | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def isSubsequence(self, s: str, t: str) -> bool: | ||
| char_to_indices = defaultdict(list) | ||
| for i in range(len(t)): | ||
| char_to_indices[t[i]].append(i) | ||
|
|
||
| char_to_next_index = {} | ||
| for ch in string.ascii_lowercase: | ||
| char_to_next_index[ch] = 0 | ||
|
|
||
| last_index = -1 | ||
| for ch in s: | ||
| char_indices = char_to_indices[ch] | ||
| while True: | ||
| if char_to_next_index[ch] >= len(char_indices): | ||
| return False | ||
|
|
||
| if char_indices[char_to_next_index[ch]] > last_index: | ||
| last_index = char_indices[char_to_next_index[ch]] | ||
| break | ||
| char_to_next_index[ch] += 1 | ||
| return True | ||
| ``` | ||
|
|
||
| - https://github.com/tokuhirat/LeetCode/pull/57/files#diff-56d94b18dcde3860786d1548afc303826c1dd1b5174a1c5baf29ccdac65c935eR30-R42 | ||
| - シンプルに書くとこのようなindexをそれぞれで動かしていく方法もあり | ||
| - https://github.com/ryosuketc/leetcode_arai60/pull/57/files#diff-d4bf0ffef278eb91530487cdf19578095c7402d9ba6698ca2a48c8c9e32cffe9R12 | ||
| - subsequence … can be none のところを自分もちゃんと意識していなかったので気を付けたい | ||
| - https://github.com/fhiyo/leetcode/pull/55/files#diff-a6c7d5ff748fd033529b0b0a550ed2aa570e18edc3e2c61da5094aec0e23a91eR45 | ||
| - follow upについて、基本的な考え方は似ている | ||
| - bisectで探す方法は考えていなかった | ||
| - 確かにindexをlast_indexから探すのはあり | ||
| - そもそも一致する可能性があまりないものを二分探索で探す発想がなかった | ||
| - 昇順になっていることを考えると計算量的には二分探索の方が良さそうだが自分のやり方のように最後に見た場所から探し始める方がHeuristicな考えとして有効な気がしなくもない | ||
| - 最後に見た場所をbisectのloに入れておくというのもありか? | ||
| - この問題に対しては処理を複雑にし過ぎているような気もする | ||
|
|
||
| ## Step 3. Final Solution | ||
|
|
||
| - 自分で最初に書いたやり方がしっくり来ていたのでちょっとだけ変えて練習 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 計算量的にはO(文字の種類*文字列の長さ)になるので状況によっては悪いですが、find がネイティブなので文字の種類が少なければ速いだろうという見積もりまであれば OK です。 |
||
|
|
||
| ```python | ||
| class Solution: | ||
| def isSubsequence(self, s: str, t: str) -> bool: | ||
| char_index = -1 | ||
| for ch in s: | ||
| char_index = t.find(ch, char_index + 1) | ||
| if char_index == -1: | ||
| return False | ||
| return True | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
last_char_index と char_index が少し把握しにくかったです。char_index はあるループで一致する文字が見つかったかを判定するために使われていると思います。
フラグ的にするか
for-else を使うことも可能かと思いました。