Spaces:
Sleeping
Sleeping
| TWO POINTERS AND SLIDING WINDOW | |
| ================================ | |
| --- TWO POINTERS TECHNIQUE --- | |
| Use two pointers (left and right) to scan an array from both ends or at different speeds. | |
| Reduces O(n^2) brute force to O(n). | |
| --- Two Sum (Sorted Array) --- | |
| Find two numbers that add up to target in a sorted array. | |
| Time: O(n). Space: O(1). | |
| def two_sum_sorted(arr, target): | |
| left, right = 0, len(arr) - 1 | |
| while left < right: | |
| total = arr[left] + arr[right] | |
| if total == target: | |
| return [left, right] | |
| elif total < target: | |
| left += 1 | |
| else: | |
| right -= 1 | |
| return [] | |
| print(two_sum_sorted([1, 2, 3, 4, 6], 6)) # [1, 3] (2+4) | |
| --- Reverse an Array In-Place --- | |
| def reverse_array(arr): | |
| left, right = 0, len(arr) - 1 | |
| while left < right: | |
| arr[left], arr[right] = arr[right], arr[left] | |
| left += 1 | |
| right -= 1 | |
| return arr | |
| print(reverse_array([1, 2, 3, 4, 5])) # [5, 4, 3, 2, 1] | |
| --- Remove Duplicates from Sorted Array --- | |
| Time: O(n). Space: O(1). | |
| def remove_duplicates(arr): | |
| if not arr: | |
| return 0 | |
| slow = 0 | |
| for fast in range(1, len(arr)): | |
| if arr[fast] != arr[slow]: | |
| slow += 1 | |
| arr[slow] = arr[fast] | |
| return slow + 1 # length of unique part | |
| arr = [1, 1, 2, 2, 3, 4, 4] | |
| k = remove_duplicates(arr) | |
| print(arr[:k]) # [1, 2, 3, 4] | |
| --- Container With Most Water --- | |
| Find two lines that form container holding most water. | |
| Time: O(n). Space: O(1). | |
| def max_water(heights): | |
| left, right = 0, len(heights) - 1 | |
| max_area = 0 | |
| while left < right: | |
| area = min(heights[left], heights[right]) * (right - left) | |
| max_area = max(max_area, area) | |
| if heights[left] < heights[right]: | |
| left += 1 | |
| else: | |
| right -= 1 | |
| return max_area | |
| print(max_water([1,8,6,2,5,4,8,3,7])) # Output: 49 | |
| --- Three Sum --- | |
| Find all triplets that sum to zero. | |
| Time: O(n^2). Space: O(n). | |
| def three_sum(nums): | |
| nums.sort() | |
| result = [] | |
| for i in range(len(nums) - 2): | |
| if i > 0 and nums[i] == nums[i-1]: | |
| continue # skip duplicates | |
| left, right = i + 1, len(nums) - 1 | |
| while left < right: | |
| total = nums[i] + nums[left] + nums[right] | |
| if total == 0: | |
| result.append([nums[i], nums[left], nums[right]]) | |
| while left < right and nums[left] == nums[left+1]: left += 1 | |
| while left < right and nums[right] == nums[right-1]: right -= 1 | |
| left += 1 | |
| right -= 1 | |
| elif total < 0: | |
| left += 1 | |
| else: | |
| right -= 1 | |
| return result | |
| print(three_sum([-1, 0, 1, 2, -1, -4])) | |
| # [[-1, -1, 2], [-1, 0, 1]] | |
| --- Trapping Rain Water --- | |
| Calculate water trapped between bars. | |
| Time: O(n). Space: O(1). | |
| def trap_water(height): | |
| left, right = 0, len(height) - 1 | |
| left_max = right_max = 0 | |
| water = 0 | |
| while left < right: | |
| if height[left] < height[right]: | |
| if height[left] >= left_max: | |
| left_max = height[left] | |
| else: | |
| water += left_max - height[left] | |
| left += 1 | |
| else: | |
| if height[right] >= right_max: | |
| right_max = height[right] | |
| else: | |
| water += right_max - height[right] | |
| right -= 1 | |
| return water | |
| print(trap_water([0,1,0,2,1,0,1,3,2,1,2,1])) # Output: 6 | |
| --- Slow/Fast Pointer: Detect Cycle --- | |
| def has_cycle(head): | |
| slow = fast = head | |
| while fast and fast.next: | |
| slow = slow.next | |
| fast = fast.next.next | |
| if slow == fast: | |
| return True | |
| return False | |
| --- SLIDING WINDOW TECHNIQUE --- | |
| Maintain a window of fixed or variable size. Slide it across array. | |
| Avoids recomputing the entire window each step. | |
| --- Maximum Sum Subarray of Size K (Fixed Window) --- | |
| Time: O(n). Space: O(1). | |
| def max_sum_subarray(arr, k): | |
| window_sum = sum(arr[:k]) | |
| max_sum = window_sum | |
| for i in range(k, len(arr)): | |
| window_sum += arr[i] - arr[i - k] | |
| max_sum = max(max_sum, window_sum) | |
| return max_sum | |
| print(max_sum_subarray([2,1,5,1,3,2], 3)) # Output: 9 (5+1+3) | |
| --- Longest Substring Without Repeating Characters (Variable Window) --- | |
| Time: O(n). Space: O(k) where k = charset size. | |
| def length_of_longest_substring(s): | |
| char_index = {} | |
| left = 0 | |
| max_len = 0 | |
| for right, ch in enumerate(s): | |
| if ch in char_index and char_index[ch] >= left: | |
| left = char_index[ch] + 1 | |
| char_index[ch] = right | |
| max_len = max(max_len, right - left + 1) | |
| return max_len | |
| print(length_of_longest_substring("abcabcbb")) # 3 (abc) | |
| print(length_of_longest_substring("pwwkew")) # 3 (wke) | |
| --- Minimum Size Subarray Sum --- | |
| Find smallest subarray with sum >= target. | |
| Time: O(n). Space: O(1). | |
| def min_subarray_len(target, nums): | |
| left = 0 | |
| curr_sum = 0 | |
| min_len = float('inf') | |
| for right in range(len(nums)): | |
| curr_sum += nums[right] | |
| while curr_sum >= target: | |
| min_len = min(min_len, right - left + 1) | |
| curr_sum -= nums[left] | |
| left += 1 | |
| return min_len if min_len != float('inf') else 0 | |
| print(min_subarray_len(7, [2,3,1,2,4,3])) # Output: 2 (4+3) | |
| --- Longest Substring with K Distinct Characters --- | |
| Time: O(n). Space: O(k). | |
| def longest_k_distinct(s, k): | |
| from collections import defaultdict | |
| char_count = defaultdict(int) | |
| left = max_len = 0 | |
| for right, ch in enumerate(s): | |
| char_count[ch] += 1 | |
| while len(char_count) > k: | |
| char_count[s[left]] -= 1 | |
| if char_count[s[left]] == 0: | |
| del char_count[s[left]] | |
| left += 1 | |
| max_len = max(max_len, right - left + 1) | |
| return max_len | |
| print(longest_k_distinct("araaci", 2)) # Output: 4 (araa) | |