### Problem Description

Given a string `s`

, find the length of the longest substring without repeating characters.

**Example 1:**

```
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
```

**Example 2:**

```
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
```

**Example 3:**

```
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
```

**Constraints:**

`0 <= s.length <= 5 * 10^4`

`s`

consists of English letters, digits, symbols, and spaces.

### Approaches

#### Approach 1: Brute Force

**Algorithm:**

- Iterate through each character in the string as the starting point.
- For each starting point, extend the substring while checking for duplicates.
- Keep track of the maximum length of substrings found.

**Time Complexity:** (O(n^3))**Space Complexity:** (O(min(n, m))) where (m) is the character set size.

**Python Code:**

```
def lengthOfLongestSubstring(s: str) -> int:
def all_unique(substring):
return len(substring) == len(set(substring))
n = len(s)
max_len = 0
for i in range(n):
for j in range(i + 1, n + 1):
if all_unique(s[i:j]):
max_len = max(max_len, j - i)
return max_len
```

#### Approach 2: Sliding Window

**Algorithm:**

- Use two pointers to represent the current window.
- Move the right pointer to expand the window until a duplicate character is found.
- Move the left pointer to shrink the window until the duplicate character is removed.
- Keep track of the maximum length of substrings found.

**Time Complexity:** (O(n))**Space Complexity:** (O(min(n, m)))

**Python Code:**

```
def lengthOfLongestSubstring(s: str) -> int:
n = len(s)
char_set = set()
left = 0
max_len = 0
for right in range(n):
while s[right] in char_set:
char_set.remove(s[left])
left += 1
char_set.add(s[right])
max_len = max(max_len, right - left + 1)
return max_len
```

#### Approach 3: Optimized Sliding Window with HashMap

**Algorithm:**

- Use a hash map to store the last index of each character.
- Move the right pointer to expand the window.
- If a duplicate character is found, update the left pointer to the position right after the last occurrence of the character.
- Keep track of the maximum length of substrings found.

**Time Complexity:** (O(n))**Space Complexity:** (O(min(n, m)))

**Python Code:**

```
def lengthOfLongestSubstring(s: str) -> int:
n = len(s)
char_index_map = {}
left = 0
max_len = 0
for right in range(n):
if s[right] in char_index_map:
left = max(left, char_index_map[s[right]] + 1)
char_index_map[s[right]] = right
max_len = max(max_len, right - left + 1)
return max_len
```

### FAQ

**Q1: What is the main idea behind the sliding window approach?**

- The sliding window approach involves maintaining a window of characters without duplicates and adjusting the window size dynamically as we encounter duplicates.

**Q2: Why is the brute force approach inefficient?**

- The brute force approach checks all possible substrings, resulting in a time complexity of (O(n^3)), which is impractical for large strings.

**Q3: How does the optimized sliding window with hash map improve performance?**

- The optimized sliding window approach uses a hash map to keep track of the indices of characters, allowing us to skip over duplicates efficiently and maintain (O(n)) time complexity.

**Q4: Can these algorithms handle strings with non-alphabetic characters?**

- Yes, all the provided algorithms can handle strings with any type of characters, including digits, symbols, and spaces.

**Q5: What is the space complexity of the sliding window approaches?**

- The space complexity is (O(min(n, m))), where (n) is the length of the string and (m) is the size of the character set. This is because the sliding window uses a set or hash map to store characters.

By understanding these approaches and their complexities, you can efficiently solve the problem of finding the longest substring without repeating characters.