-
Notifications
You must be signed in to change notification settings - Fork 0
3. Longest Substring Without Repeating Characters #3
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,45 @@ | ||
| #if __has_include("../debug.hpp") | ||
| #include "../debug.hpp" | ||
| #endif | ||
| // ここまでローカルでのデバッグ用なので気にしないでください -------------------- | ||
|
|
||
| #include <bits/stdc++.h> | ||
|
|
||
| using namespace std; | ||
|
|
||
| // <時間> | ||
| // 不明(次から測る) | ||
| // <選定事項と理由> | ||
| // mapではなくvector:最悪ケース(256文字すべて使う)のメモリはどちらも同じだから。 | ||
| // <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)> | ||
| // - unique_str_beginの代わりにbegin。流石にbeginじゃ分からない? | ||
| // 他の人ので単にleftとしているものがあったが、これでもよいだろうか? | ||
| // Goで書かれるとなぜか短くても理解できてしまうところがある。 | ||
| // - iの代わりにend。これだとなんのendか分からない。ならunique_str_endは? | ||
| // これもunique_str_end単体で使う場面があって気持ち悪い。 | ||
| // - begin&end、またはfirst&lastは半開区間[begin,end)を表すイメージがある。 | ||
| // 閉区間を表す単語はないものか。left&rightにそのイメージはありますか? | ||
| // - char_codeをasciiにしたら文字数が減ること。 | ||
| // でもasciiとは限らないと思った(なおその場合char_code_to...は0x80要素用意すれば十分か) | ||
|
|
||
| // なお以下で出てくるコメントはプロダクト版にも書くつもりのコメント | ||
| class Solution { | ||
| public: | ||
| int lengthOfLongestSubstring(string s) { | ||
| vector<int> char_code_to_last_index(256, -1); | ||
|
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. 固定長かつ十分にサイズが小さいのであれば、
Owner
Author
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.
はい、分かります。配列にしたいと思います!ありがとうございます! 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.
念のため、違いを説明してみていただけますか?
他の方のコードレビューにコメントがついていたと思います。そちらを参照されることをおすすめいたします。 他の方のコメントを調べていらっしゃらないのでしょうか。
Owner
Author
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.
|テキスト領域|データ領域|ヒープ領域|空き・共有ライブラリ等|スタック領域| スタックはスタックポインタ(rspレジスタ)をずらす(四則演算)だけでメモリの確保ができます。速度が速い代わりに、あらかじめ与えられた領域以上は使えません。
すみません…、見つかりません…。申し訳ないのですが、どこにあるでしょうか?
回答は見ていたのですが、レビューコメントまで見てませんでした。 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.
この書式は何を表そうとしたのですか?
ここで言う速度とは何を表していますか?スループットですか?レイテンシーですか?何と比べて速度が速いのですか?なぜ速度が速いのですか?本当に速いのですか?
実利用環境においては、サイズは何によって制限されますか?
何と比べて遅いのですか?なぜ遅いのですか?本当に遅いのですか?
自分の勘違いでした。失礼いたしました。
Owner
Author
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.
仮想アドレス空間0~0x7fffffffffffのメモリの使われ方を先頭から順に左から書きました。
メモリを確保する処理速度が速いということです。引き算命令一個でメモリを確保することが出来ます。
対してヒープでは、バディシステムの場合管理用のリンクリストを走査して空き領域を見つける動作があります。
物理メモリに乗っているという意味では他のプロセスのメモリの量と、それらがどれだけアクティブであるか(ページアウトしないか)によると思います。それからプロセステーブル等、カーネル側で物理メモリに常駐させたいものがあるじゃないかと思います。
承知しました。ありがとうございます! 僕は今まで実行ファイルにスタックサイズが書き込まれていると思っていたのですが、僕の環境ではデフォルトだと書き込まれていませんでした。(これが正しいスタックサイズの調べ方か分かりませんが
Owner
Author
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.
スタックはブロックスコープを抜ければ勝手に解放されます。(スタックポインタがずれて範囲外に出るだけ) マルチスレッドの時のスタックがどこに確保されるのか曖昧だったので調べたのですが、ヒープ上みたいですね。 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.
元の話題はスタックメモリとヒープメモリの違いでした。仮想アドレス空間の話はレイヤーが異なっており、その話が出てくることに違和感を感じました。
これは明示的に書いていただかないと分かりませんでした。
スループットとレイテンシーは、メモリからデータを読み込むときの話です。速度と言われてメモリの読み込みにかかる時間を連想しました。メモリの確保の時間を連想する人は少ないかもしれません。
局所性が効くとどうなりますか?
実機で計測するにはどのようにしますか?
物理メモリの容量と、仮想メモリに使用するストレージの容量の両方について話さないことに違和感を感じました。
そのあたりは自分は詳しくありません。ご自身でお調べいただき、ここで共有いただくのがよいと思います。
Owner
Author
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.
スタックとヒープがどこで確保されるかを示したつもりでした。まあ確かに関係ないですかね。
なるほどです。勉強になります!
こちらは確保にかかる時間ではなく、アクセスにかかる時間が早くなります。CPUキャッシュに載っている確率が高くなるからです。
ヒープメモリの確保速度は、それまでにどれだけのメモリが使われたか、それらのメモリがそれぞれ要求されたサイズはどれくらいか、その順番、等によると思います。
今回の場合だったら、どちらも要求メモリ量は128バイトに設定して、確保直後に解放を繰り返せばいい(というか配列+-1フィルと
すみません、物理メモリサイズの方は別にコンテナになってて容量が調整可能みたいなことを考えていたわけではないのですが、単純に当たり前だったので言及を忘れていました。
承知しました。あとで調べた結果を書きたいと思います! 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.
実際に実験してみて、結果を提示してみていただけますか?
実験をするのであれば、最もシンプルな条件から始めるのがよいと思います。自分なら、
と順々に増やしていき、バイト数と確保にかかる時間の相関を調べると思います。
alloca() 関数でスタックメモリに領域を確保することができます。ただし、この機能は現在は推奨されていないようです。
その方法ですと、ループの実行にかかった時間が結果に含まれてしまい、メモリの確保と解放にかかる時間のみを計測したことにならないと思います。メモリの確保と解放にかかる時間のみを計測するにはどうしますか? さらに言えば、
と言っているのですから、「何倍違う」ではなく、何命令もしくは何 ns 程度かかるかを結果として出力するのが妥当ではないでしょうか。
これはどういう意味で最悪なのですか?
-1 で埋める操作が含まれるため、メモリの確保と解放にかかる時間のみを計測できていないように思います。メモリの確保と解放にかかる時間のみを計測するにはどうしますか? |
||
| int max_len = 0, unique_str_begin = 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. 好みの問題ですが、このくらいのスコープであれば、unique_str_beginはもう少し単純な変数名で良いかとも思いました。(start, window_start など)
Owner
Author
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.
僕も長すぎないかと気になっていたところです |
||
|
|
||
| for (int i = 0; i < s.size(); ++i) { | ||
| unsigned char char_code = s[i]; | ||
|
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.
Owner
Author
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. あ、すみません、charの話をコメントに書き忘れていました。 僕の認識では、charはsignedするコンパイラとunsignedとするコンパイラ両方があって、なのでunsigned charに強制しています。 とはいえ0x80以上の文字コードが使われなければ考えなくて良い話ではあります。 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.
そういうことはないでしょう。
この問題ではcharの保持する値はASCIIと考えて問題ないでしょう。 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. 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. https://cpprefjp.github.io/reference/string/basic_string.html 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. 私は、@philip82148 さんの説明を以下のように解釈しましたが、どんな文字エンコーディングを使っているか分からない状況は考えなくても良いと思いました。 charはASCII以外の文字エンコーディングを使っているかもしれないので、charの取りうる値は全て"English letters, digits, symbols and spaces"の可能性がある。charがsigned charだとすると、負の値が"English letters, digits, symbols and spaces"である可能性を否めないので、unsigned charにキャストして、vectorのインデックスとして使い、出現回数をカウントする。 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.
0x80 以上を使う代表的なものとして、
があります。 @nodchip @liquo-rice 私も考えなくていいに一票。 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. 本当に、EBCDIC 環境で動くようにすべてのソースコードを管理しているならばともかく、UTF-8 にも対応せず「C++ の仕様書上これは実装依存で、1バイトの文字コードならどれでもいけるように書いた」と主張するのはバランスを欠く気がしますね。 これ、基本的にバランスを取るゲームなので、ある状況において正しいことを強く主張しないほうがいいでしょう。 Python の話ですが、バランスについては下を参照。
Owner
Author
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. なるほどです!charとして扱って、128要素でやりたいと思います! |
||
|
|
||
| if (char_code_to_last_index[char_code] >= unique_str_begin) { | ||
| unique_str_begin = char_code_to_last_index[char_code] + 1; | ||
| } | ||
|
|
||
| // [unique_str_begin, i]は文字が重複しない範囲 | ||
| max_len = max(max_len, i - unique_str_begin + 1); | ||
| char_code_to_last_index[char_code] = i; | ||
| } | ||
| return max_len; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #if __has_include("../../debug.hpp") | ||
| #include "../../debug.hpp" | ||
| #endif | ||
| // ここまでローカルでのデバッグ用なので気にしないでください -------------------- | ||
|
|
||
| #include <algorithm> | ||
| #include <string> | ||
|
|
||
| using namespace std; | ||
|
|
||
| // <時間> | ||
| // 6分 | ||
| // <疑問・不安点(・個人的な感想、違う意見があれば教えてほしいもの)> | ||
|
|
||
| // なお以下で出てくるコメントはプロダクト版にも書くつもりのコメント | ||
| class Solution { | ||
| public: | ||
| int lengthOfLongestSubstring(string s) { | ||
| int ascii_to_last_index[128]; | ||
| for (int i = 0; i < 128; ++i) ascii_to_last_index[i] = -1; | ||
|
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.
Owner
Author
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. fill、そうでした… |
||
|
|
||
| int max_len = 0, begin = 0; | ||
| for (int i = 0; i < s.size(); ++i) { | ||
| if (ascii_to_last_index[s[i]] >= begin) { | ||
| begin = ascii_to_last_index[s[i]] + 1; | ||
| } | ||
|
Comment on lines
+24
to
+26
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.
Owner
Author
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. 全然気づかなかったです |
||
| ascii_to_last_index[s[i]] = i; | ||
|
|
||
| // [begin, i]が文字が重複しない範囲 | ||
| max_len = max(max_len, i - begin + 1); | ||
| } | ||
| return max_len; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # 3. Longest Substring Without Repeating Characters | ||
|
|
||
| <https://leetcode.com/problems/longest-substring-without-repeating-characters/description/> |
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.
128