diff --git a/docs/data-structure-and-algorithms/algorithms/sliding-window.md b/docs/data-structure-and-algorithms/algorithms/sliding-window.md
index cf6efe2d..ac93f882 100644
--- a/docs/data-structure-and-algorithms/algorithms/sliding-window.md
+++ b/docs/data-structure-and-algorithms/algorithms/sliding-window.md
@@ -4,43 +4,89 @@ sidebar_position: 3
# Sliding Window
-The **Sliding Window** technique involves using a window (a subset of elements) that slides over an array or string to solve problems involving subarrays, substrings, or ranges. The window can expand, contract, or move to maintain specific properties like size or sum.
+:::tip[Status]
-This approach reduces the time complexity of problems that would otherwise require nested loops (O(n²)) to linear time (O(n)).
+This note is complete, reviewed, and considered stable.
+
+:::
+
+The **Sliding Window** technique is a powerful algorithmic pattern where we use a "window" (a subset of consecutive elements) that slides over a collection, such as an array or string. By maintaining this window and updating it as we move, we can solve complex range-based problems with optimal efficiency.
+
+This approach allows us to reduce time complexity from nested loops (O(n²)) to linear time (O(n)) by avoiding redundant calculations.
+
+## How It Works
+
+We maintain two pointers that define the boundaries of our window. As we slide the window across the data:
+
+1. **Expand**: We move the right pointer to include new elements in our window.
+2. **Process**: We update our current state (e.g., sum, count, or frequency map) with the new element.
+3. **Contract**: If our window violates a specific constraint, we move the left pointer to shrink the window until the constraint is met again.
## Types of Sliding Windows
-1. **Fixed-Sized Window**:
+### Fixed-Size Window
- - The window size remains constant while sliding.
- - Example: Maximum sum of subarray of size `k`.
+In this scenario, our window maintains a constant length `k` as it moves from start to end.
+
+
+
+```mermaid
+graph LR
+ subgraph "Array: [1, 3, -1, -3, 5, 3]"
+ A[1] --- B[3] --- C[-1] --- D[-3] --- E[5] --- F[3]
+ end
+ W[Window Size k=3] --> A
+ W --> B
+ W --> C
+ W -.->|Slide| B
+ W -.->|Slide| C
+ W -.->|Slide| D
+ style W fill:#f9f,stroke:#333,stroke-width:2px
+```
-2. **Dynamic-Sized Window**:
+
- - The window size changes based on conditions (e.g., constraints on the sum, distinct elements).
- - Example: Smallest subarray with a sum greater than `x`.
+- **Example**: Finding the maximum sum of any subarray of size `k`.
-## Time Complexity
+### Dynamic-Sized Window
-- **Efficient**: Sliding Window often processes each element once, resulting in O(n) time complexity.
-- The space complexity depends on the problem (e.g., using additional data structures like hash maps or sets).
+The size of our window grows or shrinks dynamically based on the problem's constraints.
-## Common Problems Solved Using Sliding Window
+
-| Problem Type | Description | Example Problem |
-| ------------------------------- | --------------------------------------------------------------- | ----------------------------------------- |
-| Maximum or Minimum Subarray Sum | Find the subarray with the largest or smallest sum. | Maximum sum subarray of size `k` |
-| Longest Substring | Find the longest substring meeting specific constraints. | Longest substring without repeating chars |
-| Smallest or Largest Subarray | Find the smallest or largest subarray meeting certain criteria. | Smallest subarray with sum ≥ `x` |
-| Frequency Analysis | Count or track elements in a fixed or dynamic window. | Count distinct elements in every subarray |
+```mermaid
+graph TD
+ subgraph "Expansion Phase"
+ E1[Left] --- E2[...] --- E3[Right]
+ E3 -->|Move Right| E4[New Element]
+ end
+ subgraph "Contraction Phase"
+ C1[Left] --- C2[...] --- C3[Right]
+ C1 -->|Move Left| C2
+ end
+```
-## Example Algorithms and Problems
+
-### Fixed-Size Window
+- **Example**: Finding the smallest subarray whose sum is greater than or equal to a target value `x`.
+
+## Time and Space Complexity
+
+- **Time Complexity**: We typically achieve **O(n)** because each element is added to and removed from the window at most once.
+- **Space Complexity**: This varies. If we only track a sum or count, it's **O(1)**. If we use a hash map or set to track frequencies or unique elements, it can be **O(k)** or **O(n)**.
+
+## Common Problems and Examples
-#### Maximum Sum of Subarray of Size `k`
+| Problem Type | Description | Example |
+| :--- | :--- | :--- |
+| **Fixed Subarray Sum** | Find the maximum or minimum sum in any window of size `k`. | Max Sum Subarray |
+| **Shortest/Longest Range** | Find a subarray meeting constraints with minimal or maximal length. | Smallest Subarray Sum |
+| **Unique Elements** | Find windows containing only distinct characters or elements. | Longest Unique Substring |
+| **Frequency Tracking** | Count or analyze occurrences within a moving window. | Distinct Element Counts |
-**Problem**: Given an array, find the maximum sum of any subarray of size `k`.
+### Example 1: Maximum Sum of Subarray of Size `k` (Fixed-Size)
+
+We calculate the initial window sum and then "slide" it by adding the next element and subtracting the one that fell out of the window.
```python
def max_sum_subarray(arr, k):
@@ -48,27 +94,22 @@ def max_sum_subarray(arr, k):
if n < k:
return -1
- # Compute the sum of the first window
+ # Initial window sum
window_sum = sum(arr[:k])
max_sum = window_sum
- # Slide the window
+ # Slide the window across the rest of the array
for i in range(k, n):
+ # Add the new element, remove the oldest one
window_sum += arr[i] - arr[i - k]
max_sum = max(max_sum, window_sum)
return max_sum
-
```
-**Time Complexity**: O(n)
-**Space Complexity**: O(1)
-
-### Dynamic-Size Window
-
-#### Smallest Subarray with Sum ≥ `x`
+### Example 2: Smallest Subarray with Sum ≥ `x` (Dynamic-Sized)
-**Problem**: Find the length of the smallest subarray with a sum greater than or equal to `x`.
+We expand the window until the sum meets our requirement, then shrink it from the left to find the smallest possible valid window.
```python
def min_subarray_len(arr, x):
@@ -80,22 +121,18 @@ def min_subarray_len(arr, x):
for right in range(n):
current_sum += arr[right]
- # Shrink the window while the sum is ≥ x
+ # Shrink the window as long as it remains valid
while current_sum >= x:
min_len = min(min_len, right - left + 1)
current_sum -= arr[left]
left += 1
return min_len if min_len != float('inf') else 0
-
```
-**Time Complexity**: O(n)
-**Space Complexity**: O(1)
-
-### Longest Substring Without Repeating Characters
+### Example 3: Longest Substring Without Repeating Characters
-**Problem**: Find the longest substring without repeating characters.
+We use a set to track elements in our current window and shrink the window whenever we encounter a duplicate.
```python
def longest_unique_substring(s):
@@ -104,66 +141,25 @@ def longest_unique_substring(s):
max_length = 0
for right in range(len(s)):
+ # If we find a duplicate, shrink from the left
while s[right] in char_set:
char_set.remove(s[left])
left += 1
+
char_set.add(s[right])
max_length = max(max_length, right - left + 1)
return max_length
-
```
-**Time Complexity**: O(n)
-**Space Complexity**: O(n)
-
-### Count Distinct Elements in Every Subarray of Size `k`
-
-**Problem**: Given an array and an integer `k`, count the number of distinct elements in every subarray of size `k`.
-
-```python
-from collections import defaultdict
-
-def count_distinct_in_window(arr, k):
- freq_map = defaultdict(int)
- result = []
-
- # Initialize the first window
- for i in range(k):
- freq_map[arr[i]] += 1
- result.append(len(freq_map))
-
- # Slide the window
- for i in range(k, len(arr)):
- # Remove the leftmost element
- freq_map[arr[i - k]] -= 1
- if freq_map[arr[i - k]] == 0:
- del freq_map[arr[i - k]]
-
- # Add the new element
- freq_map[arr[i]] += 1
-
- # Add the count of distinct elements to the result
- result.append(len(freq_map))
-
- return result
-
-```
-
-**Time Complexity**: O(n)
-**Space Complexity**: O(k)
-
-## Advantages of Sliding Window
+## Advantages of the Technique
-- **Efficiency**: Reduces nested loops (O(n²)) to linear (O(n)) solutions.
-- **Simplicity**: Often straightforward to implement for problems involving subarrays or substrings.
-- **Scalability**: Performs well for large input sizes.
+1. **Performance**: We eliminate the need for O(n²) nested loops in most range-based problems.
+2. **Scalability**: Our solutions handle large datasets efficiently due to the linear time complexity.
+3. **Simplicity**: Once we understand the expand/contract logic, it becomes a very intuitive way to process sequential data.
-## When to Use Sliding Window
+## When to Use It
-1. **Subarray or Substring Problems**:
- - Finding ranges or subsequences with specific constraints.
-2. **Optimizations**:
- - Maximizing or minimizing a property within a range.
-3. **Frequency Tracking**:
- - Counting occurrences or distinct elements within a window.
+- When we need to find a **subarray** or **substring** that satisfies a specific condition.
+- When we are tasked with finding the **maximum**, **minimum**, or **optimal** range of elements.
+- When we need to perform **running calculations** (sums, averages, frequencies) over a moving range.
diff --git a/docs/data-structure-and-algorithms/algorithms/two-pointers.md b/docs/data-structure-and-algorithms/algorithms/two-pointers.md
index 26b29efd..fc35d8f2 100644
--- a/docs/data-structure-and-algorithms/algorithms/two-pointers.md
+++ b/docs/data-structure-and-algorithms/algorithms/two-pointers.md
@@ -4,43 +4,90 @@ sidebar_position: 4
# Two Pointers
-The **Two Pointers** technique involves using two pointers (or indices) to traverse or manipulate a data structure, typically an array or string. These pointers can move in the same direction, opposite directions, or with one pointer lagging behind the other.
+:::tip[Status]
-This technique is particularly useful for problems involving searching, sorting, or comparing elements in arrays.
+This note is complete, reviewed, and considered stable.
-## Key Scenarios for Two Pointers
+:::
-1. **Opposite Direction (Start and End)**:
- - Used when the problem involves comparisons or operations on both ends of the array.
- - Example: Checking if an array is a palindrome.
-2. **Same Direction (Sliding)**:
- - Both pointers move in the same direction to explore different ranges or maintain a dynamic window.
- - Example: Sliding window problems like finding the smallest subarray with a given sum.
-3. **Fixed vs Moving**:
- - One pointer is fixed, while the other traverses the array to find a solution.
- - Example: Finding pairs with a specific sum.
+The **Two Pointers** technique is a powerful algorithmic pattern where we use two indices (pointers) to traverse or manipulate a data structure, typically an array or string. By coordinating the movement of these pointers, we can often solve complex problems with optimal time and space complexity.
-## Time Complexity
+We typically move these pointers in the same direction, opposite directions, or at different speeds (slow and fast pointers).
-- **Efficient**: Most Two Pointers algorithms run in O(n) because each pointer usually traverses the array only once.
-- Some problems may require preprocessing like sorting, which adds an additional O(n log n).
+## How It Works
-## Common Problems Solved Using Two Pointers
+We use two pointers to keep track of indices as we iterate through a collection. The logic depends on the specific strategy:
-| Problem Type | Description | Example Problem |
-| ------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------- |
-| Finding Pairs with a Target Sum | Check if there are two elements in an array that add up to a target value. | Two Sum (sorted array) |
-| Sorting-related Comparisons | Merge two sorted arrays, remove duplicates, etc. | Merging sorted arrays |
-| Palindrome Check | Determine if a string or array is a palindrome. | Check Palindrome |
-| Removing Elements | Filter elements or modify an array in-place. | Remove duplicates from sorted array |
-| Window-based Optimization | Find subarrays or windows meeting specific criteria. | Longest substring without repeating chars |
+- **Opposite Direction**: We start one pointer at the beginning and the other at the end, moving them toward each other.
+- **Fast and Slow**: Both pointers start at the same point, but one moves faster or under different conditions than the other.
+- **Sliding Window**: We maintain a range (a "window") between the two pointers that expands or contracts based on the problem's constraints.
-## Example Algorithms and Problems
+## Key Scenarios
-### Finding Pairs with a Target Sum
+### Opposite Direction (Start and End)
-Two pointers approach is ideal for sorted arrays.
-**Problem**: Find if a pair in the array sums to a given target.
+We use this when we need to compare or process elements from both ends of a sorted array or a string.
+
+
+
+```mermaid
+graph LR
+ subgraph "Array: [1, 2, 3, 4, 10]"
+ A[1] --- B[2] --- C[3] --- D[4] --- E[10]
+ end
+ L[Left Pointer] --> A
+ R[Right Pointer] --> E
+ L -.-> R
+ R -.-> L
+ style L fill:#f9f,stroke:#333,stroke-width:2px
+ style R fill:#bbf,stroke:#333,stroke-width:2px
+```
+
+
+
+- **Example**: Checking if an array is a palindrome or finding pairs with a specific sum in a sorted array.
+
+### Same Direction (Fast and Slow)
+
+We move both pointers from the start, but at different speeds. This is often used to detect cycles or find midpoints.
+
+
+
+```mermaid
+graph LR
+ subgraph "Array Index: 0 1 2 3 4"
+ A[1] --- B[1] --- C[2] --- D[2] --- E[3]
+ end
+ S[Slow Pointer] --> A
+ F[Fast Pointer] --> B
+ S -.-> B
+ F -.-> C
+ style S fill:#f9f,stroke:#333,stroke-width:2px
+ style F fill:#bbf,stroke:#333,stroke-width:2px
+```
+
+
+
+- **Example**: Moving duplicates to the end of an array or detecting a cycle in a linked list.
+
+## Time and Space Complexity
+
+- **Time Complexity**: Most Two Pointers solutions run in **O(n)** because each pointer usually traverses the collection only once.
+- **Space Complexity**: These algorithms are highly space-efficient, typically requiring only **O(1)** additional space.
+- **Preprocessing**: If the data isn't sorted and the strategy requires it, we might need an initial sort step, adding **O(n log n)** to the total time.
+
+## Common Problems and Examples
+
+| Problem Type | Description | Example |
+| :--- | :--- | :--- |
+| **Target Sum** | Find if two elements add up to a target value in a sorted array. | Two Sum (Sorted) |
+| **Palindrome** | Check if a string reads the same forward and backward. | Palindrome Check |
+| **In-place Modification** | Filter or remove elements without using extra space. | Remove Duplicates |
+| **Sliding Window** | Find a subarray or substring meeting specific criteria. | Longest Substring |
+
+### Example 1: Finding Pairs with a Target Sum
+
+This approach is ideal for sorted arrays. We adjust our pointers based on whether the current sum is too high or too low.
```python
def two_sum_sorted(arr, target):
@@ -51,22 +98,16 @@ def two_sum_sorted(arr, target):
if current_sum == target:
return (arr[left], arr[right])
elif current_sum < target:
- left += 1
+ left += 1 # Need a larger sum
else:
- right -= 1
+ right -= 1 # Need a smaller sum
return None
```
-**Time Complexity**:
-
-- Sorting: O(n log n) (if not sorted already)
-- Two Pointers: O(n)
-- Overall: O(n log n)
-
-### Check if a String is a Palindrome
+### Example 2: Check if a String is a Palindrome
-Use two pointers to compare characters from both ends.
+We use two pointers to compare characters from both ends moving inward.
```python
def is_palindrome(s):
@@ -81,11 +122,9 @@ def is_palindrome(s):
return True
```
-**Time Complexity**: O(n)
+### Example 3: Remove Duplicates from Sorted Array
-### Remove Duplicates from Sorted Array
-
-Modify the array in-place to remove duplicates.
+We use a "write" pointer and a "read" pointer to modify the array in-place.
```python
def remove_duplicates(nums):
@@ -94,6 +133,7 @@ def remove_duplicates(nums):
write_pointer = 1
for read_pointer in range(1, len(nums)):
+ # If we find a new unique element
if nums[read_pointer] != nums[read_pointer - 1]:
nums[write_pointer] = nums[read_pointer]
write_pointer += 1
@@ -101,17 +141,15 @@ def remove_duplicates(nums):
return write_pointer
```
-**Time Complexity**: O(n)
-**Space Complexity**: O(1)
-
-## Advantages of Two Pointers
+## Advantages of the Technique
-- **Efficiency**: Often reduces O(n²) solutions to O(n).
-- **Space-Saving**: Typically requires O(1) additional space.
-- **Simplicity**: Straightforward to implement for many problems.
+1. **Efficiency**: We often reduce complexity from O(n²) to O(n).
+2. **Memory**: We avoid creating extra copies of the data structure (O(1) space).
+3. **Clarity**: The logic is typically cleaner and easier to reason about than nested loops.
-## When to Use Two Pointers
+## When to Use It
-1. **Array or String Problems**: Involve ranges, pairs, or comparisons.
-2. **Sorted Data**: Exploit order for quick navigation.
-3. **Optimization Problems**: Maximize/minimize a value within constraints.
+- When we are dealing with **sorted** arrays or strings.
+- When we need to find pairs, triplets, or subarrays that satisfy a condition.
+- When we need to modify an array **in-place** to save memory.
+- When we are looking for a **window** of data within a larger set.