Use two indices (left and right) moving toward each other orin the same direction.
Works on sorted arrays or when searching for pairs.
example
// JavaScript — Find pair that sums to target in sorted arrayfunction twoSumSorted(arr, target) {
let left = 0, right = arr.length - 1;
while (left < right) {
const sum = arr[left] + arr[right];
if (sum === target) return [left, right];
elseif (sum < target) left++;
else right--;
}
return [-1, -1];
}
# Pythondef two_sum_sorted(arr, target):
left, right = 0, len(arr) - 1while left < right:
total = arr[left] + arr[right]
if total == target:
return [left, right]
elif total < target:
left += 1else:
right -= 1return [-1, -1]
output
twoSumSorted([1,3,5,7,9], 8) → [1, 3]
Note Time O(n), Space O(1). Requires sorted input for the converging pattern. Edge cases: empty array, single element, no valid pair. Tell the interviewer you chose two pointers over hash map to achieve O(1) space.
two pointerssorted array pairtwo sum sortedconverging pointers
Sliding Window
syntax
Maintain a window [left..right] and expand/shrink to satisfy a condition.
Fixed-size window: move both pointers together.
Variable-size window: expand right, shrink left when constraint violated.
example
// JavaScript — Max sum subarray of size kfunction maxSumWindow(arr, k) {
let windowSum = 0, maxSum = -Infinity;
for (let i = 0; i < arr.length; i++) {
windowSum += arr[i];
if (i >= k) windowSum -= arr[i - k];
if (i >= k - 1) maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}
# Python — Max sum subarray of size kdef max_sum_window(arr, k):
window_sum = 0
max_sum = float('-inf')
for i in range(len(arr)):
window_sum += arr[i]
if i >= k:
window_sum -= arr[i - k]
if i >= k - 1:
max_sum = max(max_sum, window_sum)
return max_sum
Note Time O(n), Space O(1). Sliding window converts O(n*k) brute force to O(n). For variable-size windows (e.g., longest substring without repeats), use a hash set to track window contents. Always clarify: is the window fixed or variable size?
sliding windowmax sum subarrayfixed windowvariable windowsubstring
Prefix Sum
syntax
Build a cumulative sum array so any range sum can be computed in O(1).
prefix[i] = sum of arr[0..i-1]
Range sum [l..r] = prefix[r+1] - prefix[l]
example
// JavaScriptfunction buildPrefix(arr) {
const prefix = [0];
for (const val of arr) {
prefix.push(prefix[prefix.length - 1] + val);
}
return prefix;
}
function rangeSum(prefix, left, right) {
return prefix[right + 1] - prefix[left];
}
# Pythondef build_prefix(arr):
prefix = [0]
for val in arr:
prefix.append(prefix[-1] + val)
return prefix
def range_sum(prefix, left, right):
return prefix[right + 1] - prefix[left]
Note Build: O(n) time, O(n) space. Query: O(1). Extremely useful when you need many range sum queries. Variant: prefix XOR for range XOR problems. For 2D grids, use 2D prefix sums with inclusion-exclusion.
prefix sumrange sum querycumulative sumsubarray sum
Kadane's Algorithm — Maximum Subarray
syntax
Track current subarray sum. If it drops below 0, reset to 0.
At each step: currentSum = max(num, currentSum + num)
Keep a global max.
example
// JavaScriptfunction maxSubarraySum(arr) {
let current = arr[0], best = arr[0];
for (let i = 1; i < arr.length; i++) {
current = Math.max(arr[i], current + arr[i]);
best = Math.max(best, current);
}
return best;
}
# Pythondef max_subarray_sum(arr):
current = best = arr[0]
for num in arr[1:]:
current = max(num, current + num)
best = max(best, current)
return best
Note Time O(n), Space O(1). Edge case: all negative numbers — algorithm still works since we initialize with arr[0]. To find the actual subarray indices, track start/end when best updates. Variant: maximum circular subarray uses total_sum - min_subarray.
lo = 0, hi = length - 1while lo <= hi:
mid = lo + (hi - lo) // 2
compare and adjust lo or hi
example
// JavaScriptfunction binarySearch(arr, target) {
let lo = 0, hi = arr.length - 1;
while (lo <= hi) {
const mid = lo + Math.floor((hi - lo) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1; // not found
}
# Pythondef binary_search(arr, target):
lo, hi = 0, len(arr) - 1while lo <= hi:
mid = lo + (hi - lo) // 2if arr[mid] == target:
return mid
elif arr[mid] < target:
lo = mid + 1else:
hi = mid - 1return -1
output
binary_search([1,3,5,7,9,11], 7) → 3
Note Time O(log n), Space O(1). Off-by-one errors are the #1 bug — practice until the template is muscle memory. Use lo <= hi when searching for exact match. Use lo < hi when narrowing to a single candidate. Always test with 0, 1, and 2 element arrays.
binary searchsorted arraysearch algorithmlog n
String Reversal
syntax
Two pointers from ends, swap toward center.
Or use built-in reverse methods.
example
// JavaScriptfunction reverseString(s) {
const chars = s.split('');
let l = 0, r = chars.length - 1;
while (l < r) {
[chars[l], chars[r]] = [chars[r], chars[l]];
l++; r--;
}
return chars.join('');
}
// Built-in: s.split('').reverse().join('')# Pythondef reverse_string(s):
chars = list(s)
l, r = 0, len(chars) - 1while l < r:
chars[l], chars[r] = chars[r], chars[l]
l += 1; r -= 1return''.join(chars)
# Built-in: s[::-1]
output
reverseString('interview') → 'weivretni'
Note Time O(n), Space O(n) due to string immutability (both JS and Python strings are immutable). In-place reversal is possible on char arrays. Common follow-ups: reverse words in a sentence, reverse only vowels, check if palindrome.
Two strings are anagrams if they have identical character frequencies.
Approach 1: Sort both and compare.
Approach 2: Build frequency map and compare.
example
// JavaScriptfunction isAnagram(s, t) {
if (s.length !== t.length) returnfalse;
const freq = {};
for (const ch of s) freq[ch] = (freq[ch] || 0) + 1;
for (const ch of t) {
if (!freq[ch]) returnfalse;
freq[ch]--;
}
returntrue;
}
# Pythondef is_anagram(s, t):
if len(s) != len(t):
returnFalse
freq = {}
for ch in s:
freq[ch] = freq.get(ch, 0) + 1for ch in t:
if freq.get(ch, 0) == 0:
returnFalse
freq[ch] -= 1returnTrue
output
is_anagram('listen', 'silent') → True
Note Frequency map: O(n) time, O(1) space (bounded by alphabet size). Sorting approach: O(n log n). Always ask: are inputs lowercase only? Unicode? This affects space analysis. Follow-up: find all anagram groups in a list of words.
Approach 1: Hash set — O(n) time, O(n) space
Approach 2: Sort first — O(n log n) time, O(1) space
Approach 3: Floyd's cycle (special constraints) — O(n) time, O(1) space
example
// JavaScript — Hash set approachfunction containsDuplicate(arr) {
const seen = new Set();
for (const val of arr) {
if (seen.has(val)) returntrue;
seen.add(val);
}
returnfalse;
}
function findDuplicate(arr) {
// Values in range [1, n], exactly one duplicateconst seen = new Set();
for (const val of arr) {
if (seen.has(val)) return val;
seen.add(val);
}
}
# Pythondef contains_duplicate(arr):
seen = set()
for val in arr:
if val in seen:
returnTrue
seen.add(val)
returnFalsedef find_duplicate(arr):
seen = set()
for val in arr:
if val in seen:
return val
seen.add(val)
Note The hash set approach is the go-to. If asked for O(1) space with values in [1,n], use Floyd's tortoise and hare or index marking (negate values). Always clarify constraints: can you modify the input? What is the value range?