Skip to content

3. Longest Substring Without Repeating Characters#5

Merged
katsukii merged 4 commits intomainfrom
3_longest
Jan 7, 2025
Merged

3. Longest Substring Without Repeating Characters#5
katsukii merged 4 commits intomainfrom
3_longest

Conversation

@katsukii
Copy link
Copy Markdown
Owner

int length = s.length();
int longest = 0;
for (int startInd = 0; startInd < length; startInd++) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この空白は意味がないため、消したほうが良いと思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たしかにそうですね。ありがとうございます。

時間計算量: O(n)

* 文字の位置を示すleftとrightをウィンドウとして定義し、先行するrightにより文字を1つずつ走査しながら各文字の最後の出現位置(index)を記録していく
* 対象文字が記録済(重複)の場合、ウィンドウの始端を最後に記録した位置の1つ先まで進める(対象位置が現在の始端より前であれば動かさない)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自分が解いたときは、文字とその文字のウィンドウ内での出現回数を HashMap で記録しておき、出現回数が 0 回になるまで left をインクリメントしていきました。各文字の最後の出現位置を記録する方式のほうが、ポインターを一気に飛ばすことができ、処理が端折れてよいと思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。たしかにそのような方法もありますね。以下のような実装になるかなと思いました。
たしかに出現位置を記録する方式の方が効率は良いですね。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashMap<Character, Integer> charCount = new HashMap<>();
        int left = 0, longest = 0;

        for (int right = 0; right < s.length(); right++) {
            char rightChar = s.charAt(right);
            charCount.put(rightChar, charCount.getOrDefault(rightChar, 0) + 1);

            while (charCount.get(rightChar) > 1) {
                char leftChar = s.charAt(left);
                charCount.put(leftChar, charCount.get(leftChar) - 1);
                left++;
            }

            longest = Math.max(longest, right - left + 1);
        }
        return longest;
    }
}

こちらも自力で思いつけなかったので勉強になりました。

@katsukii katsukii merged commit 6f5f00b into main Jan 7, 2025

### 試行1 HashSetに格納する方法

時間計算量: O(n^2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n^2 というけれども、endInd は文字の種類までしか伸びないはずなので、長さを n、文字の種類を k として O(nk) でしょうね。

public int lengthOfLongestSubstring(String s) {
int length = s.length();
int longest = 0;
for (int startInd = 0; startInd < length; startInd++) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ind は私は通じない気がします。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。indexと書くようにします。

class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> lastIndex = new HashMap<>();
int length = s.length(), left = 0, longest = 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一気に初期化するのは個人的には好みません。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちら、必要に応じてということですね。
一気に初期化するクセがついてしまっていたので参考にさせていただきます。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、単に3行に分けたらというくらいのことです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、そういうことだったのですね。承知しました。


## Step 3
今度は、時間を測りながら、もう一回書く。
アクセプトされたら消すを3回連続できたら問題はOK。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これでいいと思います。ちょっと空行が多いと思います。あまり多くても読む助けにならないので、適切なところを考えてください。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たしかに言われてみて見返したら空行が多いですね。ご指摘ありがとうございます。

Copy link
Copy Markdown

@philip82148 philip82148 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いいと思います!

for (int startInd = 0; startInd < length; startInd++) {
HashSet<Character> appeared = new HashSet<>();

char start = s.charAt(startInd);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは不要ですかね。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants