4 min read
Arrays & Strings: Core Operations and Patterns
Why Patterns Matter
In algorithmic interviews and high-performance computing, the difference between an
Core Algorithmic Patterns
1. Two Pointers
- Mechanism: Use two indices (often
leftandright) to scan the array. One might move from the start and the other from the end, or both might move at different speeds. - Use Case: Searching in sorted arrays, reversing strings, or finding pairs.
2. Sliding Window
- Mechanism: Maintain a sub-segment (“window”) that moves over the dataset. The window can be fixed-size or variable.
- Use Case: Finding the longest substring with K distinct characters, or the maximum sum subarray of size K.
3. Prefix Sums
- Mechanism: Pre-compute an array where
prefix[i]stores the sum of all elements from0toi. - Use Case: Calculating the sum of any subarray in
time after setup.
Practice Exercise
- Two Sum: Find indices of two numbers that add up to a target.
- Sorted Squares: Given a sorted array (with negatives), return an array of their squares in sorted order.
- Maximum Sum Subarray: Find the max sum of any subarray of size
K.
Answer
1. Two Sum ( Time, Space)
public int[] TwoSum(int[] nums, int target) {
var seen = new Dictionary<int, int>();
for (int i = 0; i < nums.Length; i++) {
int complement = target - nums[i];
if (seen.ContainsKey(complement)) {
return new int[] { seen[complement], i };
}
seen[nums[i]] = i;
}
return Array.Empty<int>();
}
2. Sorted Squares ( Two-Pointer approach)
public int[] SortedSquares(int[] nums) {
int n = nums.Length;
int[] result = new int[n];
int left = 0, right = n - 1;
// Fill from largest to smallest
for (int i = n - 1; i >= 0; i--) {
if (Math.Abs(nums[left]) > Math.Abs(nums[right])) {
result[i] = nums[left] * nums[left];
left++;
} else {
result[i] = nums[right] * nums[right];
right--;
}
}
return result;
}
3. Max Sum Subarray of Size K ( Sliding Window)
public int MaxSubarraySum(int[] nums, int k) {
int maxSum = 0, currentWindowSum = 0;
for (int i = 0; i < nums.Length; i++) {
currentWindowSum += nums[i];
// Once we hit window size, start sliding
if (i >= k - 1) {
maxSum = Math.Max(maxSum, currentWindowSum);
currentWindowSum -= nums[i - (k - 1)]; // Remove the element exiting the window
}
}
return maxSum;
}
Summary
- Two Pointers reduce
nested loops to linear scans. - Sliding Window efficiently tracks ranges in dynamic datasets.
- Prefix Sums trade space for speed in range-query scenarios.
Always look for these patterns before settling for a “brute-force” nested loop solution.