From e3f2e202e05d021ac4fdcdb926fc4f699200856a Mon Sep 17 00:00:00 2001 From: Ryotaro Kurita Date: Sun, 2 Mar 2025 13:26:59 +0900 Subject: [PATCH 1/2] finish --- .../brute_force.cpp | 19 ++++++++ .../memo.md | 44 +++++++++++++++++++ .../step1.cpp | 20 +++++++++ .../step2.cpp | 21 +++++++++ .../step3.cpp | 17 +++++++ 5 files changed, 121 insertions(+) create mode 100644 3_LongestSubstringWithoutRepeatingCharacters/brute_force.cpp create mode 100644 3_LongestSubstringWithoutRepeatingCharacters/memo.md create mode 100644 3_LongestSubstringWithoutRepeatingCharacters/step1.cpp create mode 100644 3_LongestSubstringWithoutRepeatingCharacters/step2.cpp create mode 100644 3_LongestSubstringWithoutRepeatingCharacters/step3.cpp diff --git a/3_LongestSubstringWithoutRepeatingCharacters/brute_force.cpp b/3_LongestSubstringWithoutRepeatingCharacters/brute_force.cpp new file mode 100644 index 0000000..6aecd7a --- /dev/null +++ b/3_LongestSubstringWithoutRepeatingCharacters/brute_force.cpp @@ -0,0 +1,19 @@ +class Solution { + public: + int lengthOfLongestSubstring(string s) { + int longest_length = 0; + + for (int start = 0; start < s.size(); start++) { + set unique_letters; + for (int end = start; end < s.size(); end++) { + if (unique_letters.contains(s[end])) { + break; + } + unique_letters.insert(s[end]); + longest_length = max(longest_length, end - start + 1); + } + } + + return longest_length; + } + }; diff --git a/3_LongestSubstringWithoutRepeatingCharacters/memo.md b/3_LongestSubstringWithoutRepeatingCharacters/memo.md new file mode 100644 index 0000000..65da5f5 --- /dev/null +++ b/3_LongestSubstringWithoutRepeatingCharacters/memo.md @@ -0,0 +1,44 @@ +## ステップ1 +まず思いついた方法は総当たりで解く方法。 +substringを作るための開始点と終了点の2つのインデックス用意する。 +setに一文字ずつ記録し重複があるのかないのか管理。 +TLEにはならないが、2つのループで全ての位置を試しているため時間計算量がO(n^2)、空間計算量はO(n) + +次にsliding windowで考える。 +こちらもsubstringを作るための開始点と終了点の2つのインデックス用意する。 +全ての位置を試すのではなく、必要な場合のみインデックスを動かす。 + +重複がない間は、set内に文字を入れながら終了点を後ろにずらす。 +重複があれば開始点の位置を前に進める。またsetから開始点にあった文字を削除する。 + +## ステップ2 +・setの変数名をunique_lettersにしたが、setに対してuniqueは助長か。 + setの中身は重複しないため。 + +・setからmapへの管理方法に変更 + mapを用いて文字ごとの登場回数を記録する方法ではsetと同じような処理になる。 + この場合setの方がシンプルな構造なのでsetが好み。 + + mapには文字ごとのindexを記録する。 + これによりwhileループで開始位置を動かしていた処理をなくすことができる。 + +・変数名はstartとendよりleftとrightが一般的か + +## ステップ3 +**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** + +## 他の方の解法 +基本方針は同じ +https://github.com/katsukii/leetcode/pull/5/commits/7dee757451b863e0166c44d43329c6863b6ac6d9 +https://github.com/Yoshiki-Iwasa/Arai60/pull/42 + +文字コードを使って使って、インデックスを管理する方法 +レビューやり取りを見ていると理解できていない箇所がちらほらあるので別途調べる +https://github.com/philip82148/leetcode-arai60/pull/3 + +自分もsetを使う方が好みでした。 +みなさん指摘されている通りindexも管理して、それを使って範囲を狭める方が効率的ですよね。 +https://github.com/fhiyo/leetcode/pull/48/commits/77b26c5a02d26112cd7ff94bf4d330afdde8a68a + +## Discorなど + diff --git a/3_LongestSubstringWithoutRepeatingCharacters/step1.cpp b/3_LongestSubstringWithoutRepeatingCharacters/step1.cpp new file mode 100644 index 0000000..7888bae --- /dev/null +++ b/3_LongestSubstringWithoutRepeatingCharacters/step1.cpp @@ -0,0 +1,20 @@ +class Solution { + public: + int lengthOfLongestSubstring(string s) { + int longest_length = 0; + + set unique_letters; + int start = 0; + for (int end = 0; end < s.size(); end++) { + while (unique_letters.contains(s[end])) { + unique_letters.erase(s[start]); + start++; + } + + unique_letters.insert(s[end]); + longest_length = max(longest_length, end - start + 1); + } + + return longest_length; + } + }; diff --git a/3_LongestSubstringWithoutRepeatingCharacters/step2.cpp b/3_LongestSubstringWithoutRepeatingCharacters/step2.cpp new file mode 100644 index 0000000..8f8f6ea --- /dev/null +++ b/3_LongestSubstringWithoutRepeatingCharacters/step2.cpp @@ -0,0 +1,21 @@ +class Solution { + public: + int lengthOfLongestSubstring(string s) { + int longest_length = 0; + + map letters_to_index; + int left = 0; + for (int right = 0; right < s.size(); right++) { + if (letters_to_index[s[right]] > 0) { + // left = letters_to_index[s[right]]だと現地点より前に + // 重複があった場合そこの位置をleftにしてしまう + left = max(letters_to_index[s[right]], left); + } + longest_length = max(longest_length, right - left + 1); + // 重複が発生した際に、その次の位置をleftにするためここで+1して記録 + letters_to_index[s[right]] = right + 1; + } + + return longest_length; + } + }; diff --git a/3_LongestSubstringWithoutRepeatingCharacters/step3.cpp b/3_LongestSubstringWithoutRepeatingCharacters/step3.cpp new file mode 100644 index 0000000..1997676 --- /dev/null +++ b/3_LongestSubstringWithoutRepeatingCharacters/step3.cpp @@ -0,0 +1,17 @@ +class Solution { + public: + int lengthOfLongestSubstring(string s) { + int longest_length = 0; + map letters_to_index; + int left = 0; + for (int right = 0; right < s.size(); right++) { + if (letters_to_index[s[right]] > 0) { + left = max(letters_to_index[s[right]], left); + } + longest_length = max(longest_length, right - left + 1); + letters_to_index[s[right]] = right + 1; + } + + return longest_length; + } + }; From 104d35b291ed52982acbc838449a7df39e78cc64 Mon Sep 17 00:00:00 2001 From: Ryotaro Kurita Date: Sat, 8 Mar 2025 11:41:14 +0900 Subject: [PATCH 2/2] add vector version --- .../vector.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 3_LongestSubstringWithoutRepeatingCharacters/vector.cpp diff --git a/3_LongestSubstringWithoutRepeatingCharacters/vector.cpp b/3_LongestSubstringWithoutRepeatingCharacters/vector.cpp new file mode 100644 index 0000000..7e8a23c --- /dev/null +++ b/3_LongestSubstringWithoutRepeatingCharacters/vector.cpp @@ -0,0 +1,19 @@ +class Solution { + public: + int lengthOfLongestSubstring(string s) { + int longest_length = 0; + // ASCII文字用の配列を-1で初期化 + vector letters_to_index(128, -1); + int left = 0; + + for (int right = 0; right < s.size(); right++) { + if (letters_to_index[s[right]] != -1) { + left = max(letters_to_index[s[right]] + 1, left); + } + longest_length = max(longest_length, right - left + 1); + letters_to_index[s[right]] = right; + } + + return longest_length; + } + };