-
Notifications
You must be signed in to change notification settings - Fork 0
392. Is Subsequence #62
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?
Conversation
| class Solution { | ||
| public: | ||
| bool isSubsequence(string s, string t) { | ||
| // 整数リテラルは非constなint&にはバインドできないので変数を用意する |
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.
CheckIsSubsequence() を呼び出したあとに source_index、 target_index の値を利用しないため、参照渡しにする必然性がないように感じました。自分なら値渡しで書くと思います。
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.
| s側ではなくt側をmapに突っ込み文字に対する出現位置を全て入れる | ||
| sを頭から一文字ずつ確認する。 | ||
| 登場位置の制約を守りながら、全ての文字が登場するかどうかを確認することで解ける。 | ||
| この方法であれば毎回t全体を探索することを避けることができる。 |
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.
s が 'a' 100 文字、 t が 'a' 10000 文字の場合、 letter_to_indices['a'] を毎回走査する必要があります。
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.
@nodchip
このケース見えておりませんでした🙇♂️ 他の箇所でレビュー頂いたbinary searchとvector letter_to_indices[128]を使う方式を追加しました。step4.cppです。
変更前
100 * 10000 = 10^5
変更後
100 * log_2(10000) = 100 * 13.28 = 1300
アクセスパターンがランダムアクセスになるため、データサイズによっては逆に遅くなるかもしれません。
この場合も認識しておきます🙇♂️
| class Solution { | ||
| public: | ||
| bool isSubsequence(string s, string t) { | ||
| map<char, vector<int>> letter_to_indices; |
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.
vector<int> letter_to_indices[128]; とすると、 map を省けるので、少し軽くなる可能性があります。
|
|
||
| bool is_matched = false; | ||
| for (int matched_index : letter_to_indices[letter]) { | ||
| if (current_index > matched_index) { |
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.
std::lower_bound() でインデックスを探すと、時間計算量的には速くなると思います。ただ、アクセスパターンがランダムアクセスになるため、データサイズによっては逆に遅くなるかもしれません。
| public: | ||
| bool isSubsequence(string s, string t) { | ||
| queue<char> letters_to_subsequence; | ||
| for (auto& letter : s) { |
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.
参照で受け取った場合、出力されるコードがアドレス経由で要素にアクセスするものになる可能性があり、処理が重くなる可能性があります。コンパイラーによる最適化が働けば問題ないのですが、期待しすぎるのもよくないと思います。 CPU のレジスターのビット幅に比べて小さい要素については、値で受け取ったほうがよいと思います。詳しくは『Effective C++ 第3版』をご覧ください。
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.
@nodchip
C++のコンパイラや実行環境によりサイズが大きくなることと組み込み型は普通値渡しと説明ございました🙇♂️
何度か読み返すようにします。
| int subsequence_index = 0; | ||
|
|
||
| for (int i = 0; i < text.size(); i++) { | ||
| if (subsequence[subsequence_index] == text[i]) { |
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.
subsequence で配列外アクセスをしているように見えたのですが、規格上は問題ないのですね。
https://timsong-cpp.github.io/cppwp/n4950/string.access
Preconditions: pos <= size().
Returns: *(begin() + pos) if pos < size(). Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object to any value other than charT() leads to undefined behavior.
読む人にとって紛らわしいため、自分なら subsequence_index == size() となるときにアクセスしないようなコードを書くと思います。
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.
ここも意識できておりませんでした。t側が大きい場合に、確かにエラ-が出そうですね。
|
|
||
| for (int i = 0; i < text.size(); i++) { | ||
| if (subsequence[subsequence_index] == text[i]) { | ||
| subsequence_index++; |
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.
subsequence_index == subsequence.size() の時に early return してもよいと思います。
| source_index++; | ||
| } | ||
| target_index++; | ||
| return CheckIsSubsequence(source_index, source, target_index, target); |
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.
この形の末尾再帰は容易にループに直せます。全体を while (1) {} でくくって、引数を代入に変えればいいのです。
問題へのリンク
https://leetcode.com/problems/is-subsequence/description/
問題文(プレミアムの場合)
備考
次に解く問題の予告
Next Permutation
フォルダ構成
LeetCodeの問題ごとにフォルダを作成します。
フォルダ内は、step1.cpp、step2.cpp、step3.cpp、divide.cpp、 map.cpp、two_pointers.cppとmemo.mdとなります。
memo.md内に各ステップで感じたことを追記します。