Skip to main content

dsa-interview-patterns

Classic coding interview patterns including two pointers, sliding window, binary search variants, fast/slow pointers, prefix sums, interval merging, and monotonic stack. Use when: solving array or string problems under interview constraints, recognising which pattern fits a given input shape, implementing cursor-based pagination, analysing date-range or sorted time-series queries, reviewing LINQ chains for hidden complexity, or teaching pattern-first problem solving.

Informations de source

Dépôt
willvelida/biotrackr
Dernière activité de la source
18 avril 2026 à 23:31
Langue détectée de SKILL.md
anglais
Étoiles
6
Forks
3

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
dsa-interview-patterns
description
Classic coding interview patterns including two pointers, sliding window, binary search variants, fast/slow pointers, prefix sums, interval merging, and monotonic stack. Use when: solving array or string problems under interview constraints, recognising which pattern fits a given input shape, implementing cursor-based pagination, analysing date-range or sorted time-series queries, reviewing LINQ chains for hidden complexity, or teaching pattern-first problem solving.
# DSA Interview Patterns ## When to Use - Approaching a new problem and needing to identify which pattern applies - Implementing or reviewing two-pointer, sliding window, or binary search logic - Teaching pattern-first problem solving (recognise the shape, apply the template) - Reviewing pagination cursor logic or date-range query strategies - Analysing activity log aggregation for hidden O(n²) in prefix sum candidates - Preparing for technical interviews with common pattern recognition ## Two Pointers Two pointers move through a collection — usually from both ends toward the middle, or both from the start at different speeds. ### Same-Direction (Fast / Slow) ```csharp // Remove duplicates from sorted array in-place (O(n) time, O(1) space) int slow = 0; for (int fast = 1; fast < nums.Length; fast++) { if (nums[fast] != nums[slow]) nums[++slow] = nums[fast]; } return slow + 1; ``` ### Opposite-Direction (Converging) ```csharp // Two-sum on sorted array (O(n) time) int left = 0, right = nums.Length - 1; while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) return (left, right); if (sum < target) left++; else right--; } ``` ### When to Use Two Pointers - Input is sorted or can be sorted - Looking for a pair / triplet satisfying a condition - Removing elements in-place - Comparing characters from both ends of a string (palindrome check) ## Sliding Window A window is a contiguous sub-sequence. Sliding window avoids the O(n²) of checking all pairs/windows by maintaining and updating a running state as the window slides. ### Fixed-Size Window ```csharp // Maximum sum of any subarray of length k — O(n) int windowSum = 0; for (int i = 0; i < k; i++) { windowSum += nums[i]; } int maxSum = windowSum; for (int i = k; i < nums.Length; i++) { windowSum += nums[i] - nums[i - k]; maxSum = Math.Max(maxSum, windowSum); } ``` ### Variable-Size Window ```csharp // Longest substring with at most k distinct characters — O(n) int left = 0, maxLen = 0; var freq = new Dictionary<char, int>(); for (int right = 0; right < s.Length; right++) { freq[s[right]] = freq.GetValueOrDefault(s[right]) + 1; while (freq.Count > k) { freq[s[left]]--; if (freq[s[left]] == 0) freq.Remove(s[left]); left++; } maxLen = Math.Max(maxLen, right - left + 1); } ``` ### Biotrackr Anchor — Pagination as Sliding Window `PaginationResponse<T>` in Biotrackr APIs is a fixed-size sliding window over a sorted dataset. Cosmos DB continuation tokens are variable-size window cursors — the boundary is a bookmark, not a numeric offset: ``` Fixed: pageNumber=3, pageSize=20 → offset = 40, length = 20 Cursor: continuationToken="{etag}" → start after last seen item ``` **Teaching angle:** Cursor-based pagination avoids "page drift" when items are inserted mid-pagination. It is the variable-size window pattern: the window start is pinned to the last seen item, not a fixed numeric offset. ## Binary Search Binary search works on any **monotone function** — not just sorted arrays. The key is: "does the condition hold for all values on one side?" ### Template ```csharp // Generalised binary search — finds leftmost position where condition is true int left = 0, right = boundary; while (left < right) { int mid = left + (right - left) / 2; if (Condition(mid)) right = mid; // condition true → search left half else left = mid + 1; // condition false → search right half } return left; // leftmost true position ``` ### Biotrackr Anchor — Date-Range Queries on Sorted Time-Series Activity, sleep, and vitals data in Biotrackr are stored sorted by `date`. A range query `/range/{startDate}/{endDate}` on sorted records is binary search applied twice: ``` find first index where date >= startDate → binary search left boundary find last index where date <= endDate → binary search right boundary ``` **Teaching angle:** Cosmos DB range queries on indexed `date` fields use a B-tree for O(log n) boundary location — the same concept as binary search, implemented in a tree. ## Fast/Slow Pointers Fast pointer moves at 2× the speed of slow. Useful for cycle detection and finding the middle of a linked list. ``` Floyd's cycle detection: slow moves 1 step at a time fast moves 2 steps at a time If they meet: cycle exists If fast reaches null: no cycle ``` ### When to Use Fast/Slow - Detect cycle in a linked list (Floyd's algorithm) - Find the middle node of a linked list - Detect duplicate in an array treated as implicit linked list (Floyd's on values) ## Prefix Sum A prefix sum array P where `P[i] = nums[0] + ... + nums[i]` allows O(1) range sum queries: ```csharp // Build prefix sum — O(n) int[] prefix = new int[nums.Length + 1]; for (int i = 0; i < nums.Length; i++) prefix[i + 1] = prefix[i] + nums[i]; // Query sum of [left, right] — O(1) int rangeSum = prefix[right + 1] - prefix[left]; ``` ### Biotrackr Anchor — Activity Log Aggregation `Biotrackr.Activity.Api` returns activity records by date. Aggregating total steps over a date range without prefix sums requires summing each record in the range: O(k) where k is the range size. With a pre-built prefix sum over sorted daily totals, any range aggregate is O(1) after O(n) preprocessing. **Teaching angle:** Build the prefix sum once; answer all range queries in O(1). The trade-off is O(n) space. When you have many range queries on static data, prefix sums are the right tool. ## Pattern Recognition Guide Use the input shape to identify the right pattern: | Input Shape | Common Patterns | |---|---| | Sorted array, find target | Binary search | | Sorted array, find pair satisfying condition | Two pointers (converging) | | Array, longest/smallest subarray satisfying condition | Sliding window | | Linked list, detect cycle or find middle | Fast/slow pointers | | Array, range sum queries | Prefix sum | | Array of intervals, merge or insert | Sort by start, linear sweep | | Matrix, find path or connected region | BFS or DFS | | String, all permutations/combinations | Backtracking | | Scheduling with priorities | Heap / priority queue | | "Nearest greater element" | Monotonic stack | ## Monotonic Stack A monotonic stack maintains elements in a consistently increasing or decreasing order. Useful for "next greater/smaller element" problems in O(n). ```csharp // Next greater element for each item — O(n) var result = new int[nums.Length]; var stack = new Stack<int>(); // stores indices for (int i = 0; i < nums.Length; i++) { while (stack.Count > 0 && nums[stack.Peek()] < nums[i]) result[stack.Pop()] = nums[i]; stack.Push(i); } // Remaining indices have no greater element → result stays 0 ``` **When to reach for monotonic stack:** "For each element, find the first element to its left/right that is larger/smaller." This pattern appears in histogram problems, stock span, and trapping rainwater.
Voir sur GitHub