Skip to content

Commit 6ee7556

Browse files
committed
add python solutions for sliding window pattern
1 parent ae700c2 commit 6ee7556

File tree

5 files changed

+726
-0
lines changed

5 files changed

+726
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Longest Substring Without Repeating Characters
2+
Given a string s, find the length of the longest substring without repeating characters.
3+
4+
### Constraints:
5+
- 0 <= s.length <= 5 * 10^4
6+
- s consists of English letters, digits, symbols, and spaces.
7+
8+
### Examples
9+
```javascript
10+
Input: s = "abcabcbb"
11+
Output: 3
12+
Explanation: The answer is "abc", with the length of 3.
13+
14+
Input: s = "bbbbb"
15+
Output: 1
16+
Explanation: The answer is "b", with the length of 1.
17+
18+
Input: s = "pwwkew"
19+
Output: 3
20+
Explanation: The answer is "wke", with the length of 3.
21+
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
22+
```
23+
24+
## Approaches to Solve the Problem
25+
### Approach 1: Brute Force (Inefficient)
26+
##### Intuition:
27+
A simple brute-force solution is to check every possible substring, and for each substring, check if it contains duplicate characters. The maximum length of a substring without repeating characters is tracked.
28+
29+
Steps:
30+
1. Use two nested loops to generate all possible substrings.
31+
2. For each substring, check if it contains duplicate characters by using a set or dictionary.
32+
3. Track the maximum length of substrings without duplicates.
33+
##### Time Complexity:
34+
O(n²) for checking all substrings and validating each one.
35+
##### Space Complexity:
36+
O(n) for storing characters in a set or dictionary while checking each substring.
37+
##### Python Code:
38+
```python
39+
def lengthOfLongestSubstring(s: str) -> int:
40+
max_len = 0
41+
n = len(s)
42+
43+
for i in range(n):
44+
seen = set()
45+
for j in range(i, n):
46+
if s[j] in seen:
47+
break
48+
seen.add(s[j])
49+
max_len = max(max_len, j - i + 1)
50+
51+
return max_len
52+
```
53+
### Approach 2: Sliding Window with Hash Set (Optimal)
54+
##### Intuition:
55+
The brute-force approach is inefficient because it recalculates the substring from scratch each time. We can improve this by using a sliding window technique, where we keep track of the current substring using two pointers, left and right, and adjust the window as necessary. A hash set is used to track characters in the current window, allowing us to efficiently check for duplicates.
56+
57+
1. Use two pointers (left and right) to create a window of characters.
58+
2. Expand the window by moving the right pointer.
59+
3. If a duplicate character is found, shrink the window from the left by moving the left pointer until the duplicate is removed.
60+
4. Track the maximum length of the window during this process.
61+
62+
Steps:
63+
1. Initialize a set to store the characters in the current window.
64+
2. Move the right pointer to expand the window.
65+
3. If the character at right is already in the set, move the left pointer to shrink the window until the character is removed.
66+
4. Keep updating the maximum length of the window.
67+
##### Visualization:
68+
```perl
69+
For s = "abcabcbb":
70+
71+
Initial state: left = 0, right = 0, window = ""
72+
Step 1: Expand window to "a"
73+
Step 2: Expand window to "ab"
74+
Step 3: Expand window to "abc" (max_len = 3)
75+
Step 4: Encounter duplicate 'a', move left to 1 (window = "bca")
76+
Step 5: Expand window to "bcab" → encounter duplicate 'b', move left to 2 (window = "cab")
77+
Continue until the entire string is processed.
78+
```
79+
##### Time Complexity:
80+
O(n), where n is the length of the string. We traverse the string once with the sliding window.
81+
##### Space Complexity:
82+
O(min(n, m)), where n is the length of the string and m is the size of the character set (e.g., 26 for lowercase English letters).
83+
##### Python Code:
84+
```python
85+
def lengthOfLongestSubstring(s: str) -> int:
86+
char_set = set()
87+
left = 0
88+
max_len = 0
89+
90+
for right in range(len(s)):
91+
# Shrink the window if we encounter a duplicate character
92+
while s[right] in char_set:
93+
char_set.remove(s[left])
94+
left += 1
95+
96+
# Add the current character to the window
97+
char_set.add(s[right])
98+
99+
# Update the maximum length
100+
max_len = max(max_len, right - left + 1)
101+
102+
return max_len
103+
```
104+
### Approach 3: Sliding Window with Hash Map
105+
##### Intuition:
106+
A further optimization can be made by using a hash map to store the last index of each character. This allows us to move the left pointer directly to the position after the last occurrence of the duplicate character, rather than shrinking the window one character at a time.
107+
108+
Steps:
109+
1. Initialize a hash map to store the last index of each character.
110+
2. Move the right pointer to expand the window.
111+
3. If a duplicate character is found, move the left pointer directly to the position after the last occurrence of the duplicate.
112+
4. Track the maximum length of the window.
113+
##### Visualization:
114+
```perl
115+
For s = "abcabcbb":
116+
117+
Initial state: left = 0, right = 0, window = "", last_occurrence = {}
118+
Step 1: Expand window to "a" → last_occurrence['a'] = 0
119+
Step 2: Expand window to "ab" → last_occurrence['b'] = 1
120+
Step 3: Expand window to "abc" → last_occurrence['c'] = 2
121+
Step 4: Encounter duplicate 'a', move left to 1 (after last 'a')
122+
Continue until the entire string is processed.
123+
```
124+
##### Time Complexity:
125+
O(n), as we still traverse the string once, but this time we move the left pointer more efficiently.
126+
##### Space Complexity:
127+
O(min(n, m)), where n is the length of the string and m is the size of the character set.
128+
##### Python Code:
129+
```python
130+
def lengthOfLongestSubstring(s: str) -> int:
131+
char_index_map = {}
132+
left = 0
133+
max_len = 0
134+
135+
for right in range(len(s)):
136+
# If the character is already in the map, move the left pointer
137+
if s[right] in char_index_map:
138+
left = max(left, char_index_map[s[right]] + 1)
139+
140+
# Update the last occurrence of the current character
141+
char_index_map[s[right]] = right
142+
143+
# Update the maximum length of the window
144+
max_len = max(max_len, right - left + 1)
145+
146+
return max_len
147+
```
148+
## Summary
149+
| Approach | Time Complexity | Space Complexity |
150+
|-----------------------------------|-----------------|------------------|
151+
| Brute Force | O(n²) | O(n) |
152+
| Sliding Window with Hash Set | O(n) | O(min(n, m)) |
153+
| Sliding Window with Hash Map | O(n) | O(min(n, m)) |
154+
155+
The Sliding Window with Hash Map is the most efficient approach because it uses a single pass over the string and minimizes the movement of the left pointer by jumping directly to the correct position.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Maximum Average Subarray I
2+
You are given an integer array nums consisting of n elements, and an integer k. Find the contiguous subarray of length k that has the maximum average value and return this value.
3+
4+
### Constraints:
5+
- n == nums.length
6+
- 1 <= k <= n <= 10^5
7+
- -10^4 <= nums[i] <= 10^4
8+
9+
### Examples
10+
```javascript
11+
Input: nums = [1,12,-5,-6,50,3], k = 4
12+
Output: 12.75
13+
Explanation: Maximum average is (12 - 5 - 6 + 50) / 4 = 12.75
14+
15+
Input: nums = [5], k = 1
16+
Output: 5.0
17+
```
18+
19+
## Approaches to Solve the Problem
20+
### Approach 1: Brute Force (Inefficient)
21+
##### Intuition:
22+
A brute force approach would involve checking all possible subarrays of length k and calculating their averages. This can be done by looping over each possible starting index, calculating the sum of the subarray, and keeping track of the maximum sum.
23+
24+
Steps:
25+
1. Loop through the array from index 0 to n - k.
26+
2. For each index i, calculate the sum of the subarray starting at i and ending at i + k - 1.
27+
3. Track the maximum sum.
28+
4. Return the maximum sum divided by k as the maximum average.
29+
##### Time Complexity:
30+
O(n * k), where n is the length of the array. For each element, we compute the sum of a subarray of length k.
31+
##### Space Complexity:
32+
O(1), as no extra space is used beyond the variables.
33+
##### Python Code:
34+
```python
35+
def findMaxAverage(nums: List[int], k: int) -> float:
36+
max_sum = float('-inf')
37+
n = len(nums)
38+
39+
for i in range(n - k + 1):
40+
current_sum = sum(nums[i:i+k])
41+
max_sum = max(max_sum, current_sum)
42+
43+
return max_sum / k
44+
```
45+
### Approach 2: Sliding Window (Optimal Solution)
46+
##### Intuition:
47+
The brute force approach is inefficient because we are recalculating the sum of each subarray from scratch. Instead, we can use the sliding window technique to optimize this. The sliding window technique allows us to update the sum of the subarray by subtracting the element that is sliding out of the window and adding the element that is sliding into the window.
48+
49+
Steps:
50+
1. Calculate the sum of the first k elements.
51+
2. For each subsequent subarray, update the sum by subtracting the element that is leaving the window (at index i - k) and adding the element that is entering the window (at index i).
52+
3. Track the maximum sum.
53+
4. Return the maximum sum divided by k as the maximum average.
54+
##### Visualization:
55+
```perl
56+
For nums = [1,12,-5,-6,50,3] and k = 4:
57+
58+
Initial window: [1, 12, -5, -6], sum = 2
59+
Move window:
60+
New window: [12, -5, -6, 50], sum = 51 (max updated)
61+
Move window:
62+
New window: [-5, -6, 50, 3], sum = 42 (max stays 51)
63+
```
64+
##### Time Complexity:
65+
O(n), where n is the length of the array. We calculate the sum for each subarray by adjusting the previous sum in constant time.
66+
##### Space Complexity:
67+
O(1), as no extra space is used beyond the variables for the sliding window.
68+
##### Python Code:
69+
```python
70+
def findMaxAverage(nums: List[int], k: int) -> float:
71+
# Step 1: Calculate the sum of the first k elements
72+
current_sum = sum(nums[:k])
73+
max_sum = current_sum
74+
75+
# Step 2: Slide the window over the array
76+
for i in range(k, len(nums)):
77+
current_sum += nums[i] - nums[i - k] # Slide the window
78+
max_sum = max(max_sum, current_sum) # Update max sum
79+
80+
# Step 3: Return the maximum average
81+
return max_sum / k
82+
```
83+
#### Edge Cases:
84+
1. Single element array: If k == 1 and the array has only one element, the result is just that element.
85+
2. All elements are the same: The sliding window will return the average of any subarray, as all values are the same.
86+
3. Negative numbers: The solution should correctly handle arrays with negative numbers and return the correct maximum average.
87+
## Summary
88+
| Approach | Time Complexity | Space Complexity |
89+
|-----------------------------------|-----------------|------------------|
90+
| Brute Force | O(n * k) | O(1) |
91+
| Sliding Window (Optimal) | O(n) | O(1) |
92+
93+
The Sliding Window approach is the most efficient solution, allowing us to find the maximum average subarray in O(n) time. It leverages the fact that we can update the sum incrementally rather than recalculating it from scratch.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Minimum Size Subarray Sum
2+
Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [nums[l], nums[l+1], ..., nums[r-1], nums[r]] of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.
3+
4+
### Constraints:
5+
- 1 <= target <= 10^9
6+
- 1 <= nums.length <= 10^5
7+
- 1 <= nums[i] <= 10^5
8+
9+
### Examples
10+
```javascript
11+
Input: target = 7, nums = [2,3,1,2,4,3]
12+
Output: 2
13+
Explanation: The subarray [4,3] has the minimal length under the problem constraint.
14+
15+
Input: target = 4, nums = [1,4,4]
16+
Output: 1
17+
18+
Input: target = 11, nums = [1,1,1,1,1,1,1,1]
19+
Output: 0
20+
```
21+
22+
## Approaches to Solve the Problem
23+
### Approach 1: Brute Force (Inefficient)
24+
##### Intuition:
25+
In the brute-force approach, we consider every possible subarray in the array. For each subarray, we compute its sum and check if it meets or exceeds the target. We track the minimum subarray length.
26+
27+
Steps:
28+
1. Use two nested loops to consider all subarrays.
29+
2. For each subarray, calculate its sum.
30+
3. If the sum is greater than or equal to the target, update the minimum subarray length.
31+
4. Return the minimum length found.
32+
##### Time Complexity:
33+
O(n²), where n is the length of the array. This approach checks every subarray.
34+
##### Space Complexity:
35+
O(1), as no extra space is used beyond variables for tracking the subarray sum and length.
36+
##### Python Code:
37+
```python
38+
def minSubArrayLen(target: int, nums: List[int]) -> int:
39+
n = len(nums)
40+
min_len = float('inf')
41+
42+
for i in range(n):
43+
current_sum = 0
44+
for j in range(i, n):
45+
current_sum += nums[j]
46+
if current_sum >= target:
47+
min_len = min(min_len, j - i + 1)
48+
break
49+
50+
return 0 if min_len == float('inf') else min_len
51+
```
52+
### Approach 2: Sliding Window (Optimal Solution)
53+
##### Intuition:
54+
The brute-force approach is inefficient because we are recalculating the sum for every subarray from scratch. We can improve this by using the sliding window technique. The idea is to maintain a window (a subarray) with two pointers, left and right, and dynamically adjust the window size as we traverse the array.
55+
56+
Start by expanding the window by moving the right pointer until the window’s sum is greater than or equal to the target.
57+
Once the window's sum is valid, shrink the window by moving the left pointer inward to minimize its size while keeping the sum greater than or equal to the target.
58+
59+
Steps:
60+
1. Initialize two pointers left and right at the start of the array.
61+
2. Maintain a running sum of the elements in the window.
62+
3. Expand the window by moving right and adding the current element to the running sum.
63+
4. If the sum is greater than or equal to the target, update the minimum length and move the left pointer 5.inward to try and shrink the window.
64+
5. Repeat until right reaches the end of the array.
65+
##### Visualization:
66+
```perl
67+
For target = 7 and nums = [2,3,1,2,4,3]:
68+
69+
Initial state: left = 0, right = 0, sum = 0
70+
71+
Step 1: Expand the window
72+
right = 0, sum = 2
73+
74+
Step 2: Expand the window
75+
right = 1, sum = 5
76+
77+
Step 3: Expand the window
78+
right = 2, sum = 6
79+
80+
Step 4: Expand the window
81+
right = 3, sum = 8 (valid window), update min_len = 4, shrink window from left
82+
83+
Step 5: Shrink window
84+
left = 1, sum = 6
85+
86+
Step 6: Expand the window
87+
right = 4, sum = 10 (valid window), update min_len = 2
88+
89+
Step 7: Shrink window
90+
left = 2, sum = 7 (valid window), update min_len = 2
91+
92+
Step 8: Shrink window further until left = 3, then exit.
93+
```
94+
##### Time Complexity:
95+
O(n), where n is the length of the array. We traverse the array once with the sliding window.
96+
##### Space Complexity:
97+
O(1), as no extra space is used beyond the sliding window and a few variables.
98+
##### Python Code:
99+
```python
100+
def minSubArrayLen(target: int, nums: List[int]) -> int:
101+
left = 0
102+
current_sum = 0
103+
min_len = float('inf')
104+
105+
for right in range(len(nums)):
106+
current_sum += nums[right]
107+
108+
# Shrink the window while sum is greater than or equal to target
109+
while current_sum >= target:
110+
min_len = min(min_len, right - left + 1)
111+
current_sum -= nums[left]
112+
left += 1
113+
114+
return 0 if min_len == float('inf') else min_len
115+
```
116+
#### Edge Cases:
117+
1. Target larger than the total sum: If the sum of all elements in nums is less than target, the function should return 0.
118+
2. Single element array: If the array has only one element, the function should handle this case properly by checking if the element is greater than or equal to the target.
119+
3. All elements are smaller than target: If all elements are smaller than the target, the algorithm should correctly identify the minimal subarray that meets the condition.
120+
## Summary
121+
| Approach | Time Complexity | Space Complexity |
122+
|-----------------------------------|-----------------|------------------|
123+
| Brute Force | O(n²) | O(1) |
124+
| Sliding Window (Optimal) | O(n) | O(1) |
125+
126+
The Sliding Window approach is the most efficient solution. It processes the array in linear time and adjusts the window dynamically, making it the optimal solution for this problem.

0 commit comments

Comments
 (0)