| name | algorithm-pattern-master |
| description | Guides mastery of core algorithmic patterns including sliding window, two pointers, binary search, greedy, and backtracking with complexity analysis
Use when the user asks about algorithm pattern master, related techniques, best practices, or needs guidance in this domain.
Do NOT use when the request is outside the scope of algorithm pattern master or requires a different specialized skill.
|
| license | Apache-2.0 |
| metadata | {"author":"foundry-skills","version":"1.0.0","tags":"advanced competitive-programming template guide beginner-friendly quick-reference testing analysis","category":"emerging-tech","subcategory":"competitive-programming","depends":"","disclaimer":"none","difficulty":"intermediate"} |
Algorithm Pattern Master
You are an expert competitive programming coach specializing in algorithmic patterns. You guide programmers through the essential patterns that appear repeatedly in contests and interviews: sliding window, two pointers, binary search on answer, greedy algorithms, and backtracking, with rigorous complexity analysis and implementation techniques.
When to Use
Use this skill when:
- User asks about algorithm pattern master techniques or best practices
- User needs guidance on algorithm pattern master concepts
- User wants to implement or improve their approach to algorithm pattern master
Do NOT use when:
- The request falls outside the scope of algorithm pattern master
- User needs a different specialized skill for their specific situation
- The topic requires professional consultation beyond general guidance
Pattern Recognition Framework
When to Apply Each Pattern
| Problem Signal | Pattern | Complexity |
|---|
| Contiguous subarray, max/min length | Sliding Window | O(n) |
| Sorted array, pair finding | Two Pointers | O(n) |
| Monotonic answer, feasibility check | Binary Search on Answer | O(n log V) |
| Local optimal leads to global optimal | Greedy | O(n log n) |
| All combinations, permutations | Backtracking | O(2^n) or O(n!) |
| Range queries, prefix property | Prefix Sums | O(n) build, O(1) query |
| Interval scheduling, overlap | Sorting + Sweep | O(n log n) |
Sliding Window
Fixed-Size Window
int maxSumSubarray(vector<int>& arr, int k) {
int n = arr.size();
if (n < k) return -1;
int windowSum = 0;
for (int i = 0; i < k; i++)
windowSum += arr[i];
int maxSum = windowSum;
for (int i = k; i < n; i++) {
windowSum += arr[i] - arr[i - k];
maxSum = max(maxSum, windowSum);
}
return maxSum;
}
Variable-Size Window (Shrinkable)
int longestKDistinct(string& s, int k) {
unordered_map<char, int> freq;
int left = 0, maxLen = 0;
for (int right = 0; right < (int)s.size(); right++) {
freq[s[right]]++;
while ((int)freq.size() > k) {
freq[s[left]]--;
if (freq[s[left]] == 0)
freq.erase(s[left]);
left++;
}
maxLen = max(maxLen, right - left + 1);
}
return maxLen;
}
Sliding Window with Monotonic Deque
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;
vector<int> result;
for (int i = 0; i < (int)nums.size(); i++) {
while (!dq.empty() && dq.front() <= i - k)
dq.pop_front();
while (!dq.empty() && nums[dq.back()] <= nums[i])
dq.pop_back();
dq.push_back(i);
if (i >= k - 1)
result.push_back(nums[dq.front()]);
}
return result;
}
Two Pointers
Opposite Direction (Two Sum on Sorted)
pair<int,int> twoSumSorted(vector<int>& arr, int target) {
int lo = 0, hi = (int)arr.size() - 1;
while (lo < hi) {
int sum = arr[lo] + arr[hi];
if (sum == target) return {lo, hi};
else if (sum < target) lo++;
else hi--;
}
return {-1, -1};
}
Same Direction (Fast/Slow)
int removeDuplicates(vector<int>& nums) {
if (nums.empty()) return 0;
int slow = 0;
for (int fast = 1; fast < (int)nums.size(); fast++) {
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
bool hasCycle(ListNode* head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}
Three Pointers (Three Sum)
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> result;
int n = nums.size();
for (int i = 0; i < n - 2; i++) {
if (i > 0 && nums[i] == nums[i-1]) continue;
int lo = i + 1, hi = n - 1;
while (lo < hi) {
int sum = nums[i] + nums[lo] + nums[hi];
if (sum == 0) {
result.push_back({nums[i], nums[lo], nums[hi]});
while (lo < hi && nums[lo] == nums[lo+1]) lo++;
while (lo < hi && nums[hi] == nums[hi-1]) hi--;
lo++; hi--;
} else if (sum < 0) lo++;
else hi--;
}
}
return result;
}
Binary Search on Answer
Template: Minimize Maximum
int binarySearchOnAnswer(vector<int>& arr, int target) {
int lo = MIN_POSSIBLE_ANSWER;
int hi = MAX_POSSIBLE_ANSWER;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (feasible(arr, mid, target)) {
hi = mid;
} else {
lo = mid + 1;
}
}
return lo;
}
Example: Split Array Largest Sum
int splitArray(vector<int>& nums, int m) {
int lo = *max_element(nums.begin(), nums.end());
int hi = accumulate(nums.begin(), nums.end(), 0);
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
int parts = 1, currentSum = 0;
for (int num : nums) {
if (currentSum + num > mid) {
parts++;
currentSum = num;
} else {
currentSum += num;
}
}
if (parts <= m)
hi = mid;
else
lo = mid + 1;
}
return lo;
}
Example: Koko Eating Bananas
int minEatingSpeed(vector<int>& piles, int h) {
int lo = 1;
int hi = *max_element(piles.begin(), piles.end());
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
long long hours = 0;
for (int p : piles)
hours += (p + mid - 1) / mid;
if (hours <= h)
hi = mid;
else
lo = mid + 1;
}
return lo;
}
Greedy Algorithms
Activity Selection / Interval Scheduling
int maxNonOverlapping(vector<pair<int,int>>& intervals) {
sort(intervals.begin(), intervals.end(),
[](auto& a, auto& b) { return a.second < b.second; });
int count = 1;
int lastEnd = intervals[0].second;
for (int i = 1; i < (int)intervals.size(); i++) {
if (intervals[i].first >= lastEnd) {
count++;
lastEnd = intervals[i].second;
}
}
return count;
}
Greedy Proof Template
To prove a greedy algorithm is optimal:
1. Greedy Choice Property:
Show that making the locally optimal choice
does not prevent reaching a globally optimal solution.
Proof by exchange argument:
- Take any optimal solution OPT
- Show you can modify OPT to include the greedy choice
- The modified solution is still optimal
2. Optimal Substructure:
Show that after making the greedy choice,
the remaining subproblem has the same structure
and can be solved optimally by the same greedy approach.
Jump Game (Greedy Reach)
bool canJump(vector<int>& nums) {
int maxReach = 0;
for (int i = 0; i <= maxReach && i < (int)nums.size(); i++) {
maxReach = max(maxReach, i + nums[i]);
}
return maxReach >= (int)nums.size() - 1;
}
int minJumps(vector<int>& nums) {
int jumps = 0, currentEnd = 0, farthest = 0;
for (int i = 0; i < (int)nums.size() - 1; i++) {
farthest = max(farthest, i + nums[i]);
if (i == currentEnd) {
jumps++;
currentEnd = farthest;
}
}
return jumps;
}
Backtracking
General Template
void backtrack(State& state, vector<Result>& results,
Candidates& candidates, int start) {
if (isComplete(state)) {
results.push_back(state);
return;
}
for (int i = start; i < candidates.size(); i++) {
if (!isValid(state, candidates[i])) continue;
state.add(candidates[i]);
backtrack(state, results, candidates, i + 1);
state.remove(candidates[i]);
}
}
Subsets (Power Set)
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
vector<int> current;
function<void(int)> backtrack = [&](int start) {
result.push_back(current);
for (int i = start; i < (int)nums.size(); i++) {
current.push_back(nums[i]);
backtrack(i + 1);
current.pop_back();
}
};
backtrack(0);
return result;
}
N-Queens
int totalNQueens(int n) {
int count = 0;
vector<bool> cols(n), diag1(2*n), diag2(2*n);
function<void(int)> solve = [&](int row) {
if (row == n) { count++; return; }
for (int col = 0; col < n; col++) {
if (cols[col] || diag1[row-col+n] || diag2[row+col])
continue;
cols[col] = diag1[row-col+n] = diag2[row+col] = true;
solve(row + 1);
cols[col] = diag1[row-col+n] = diag2[row+col] = false;
}
};
solve(0);
return count;
}
Prefix Sums
1D and 2D Prefix Sums
class PrefixSum1D {
vector<long long> prefix;
public:
PrefixSum1D(vector<int>& arr) {
int n = arr.size();
prefix.resize(n + 1, 0);
for (int i = 0; i < n; i++)
prefix[i+1] = prefix[i] + arr[i];
}
long long query(int l, int r) {
return prefix[r+1] - prefix[l];
}
};
class PrefixSum2D {
vector<vector<long long>> prefix;
public:
PrefixSum2D(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
prefix.assign(m+1, vector<long long>(n+1, 0));
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
prefix[i][j] = mat[i][j] + prefix[i][j]
+ prefix[i][j] - prefix[i][j];
}
{
prefix[r2][c2] - prefix[r1][c2]
- prefix[r2][c1] + prefix[r1][c1];
}
};
Complexity Analysis Quick Reference
| Pattern | Time | Space | Key Insight |
|---|
| Sliding window (fixed) | O(n) | O(1) | Each element enters/leaves once |
| Sliding window (variable) | O(n) | O(k) | Left pointer never moves backward |
| Two pointers (sorted) | O(n) | O(1) | Total pointer moves = O(n) |
| Binary search on answer | O(n log V) | O(1) | V = search space range |
| Greedy + sort | O(n log n) | O(1) | Sort dominates |
| Backtracking (subsets) | O(2^n) | O(n) | Decision tree has 2^n leaves |
| Backtracking (permutations) | O(n!) | O(n) | n choices, then n-1, then n-2... |
| Prefix sums (1D) | O(n) / O(1) | O(n) | Build once, query O(1) |
| Prefix sums (2D) | O(mn) / O(1) | O(mn) | Inclusion-exclusion principle |
Common Pitfalls
| Mistake | Impact | Fix |
|---|
| Off-by-one in binary search | Infinite loop or wrong answer | Test with 1 and 2 element cases |
| Integer overflow in binary search | Undefined behavior | Use lo + (hi - lo) / 2 |
| Not handling duplicates in two pointers | Duplicate triplets/pairs | Skip equal adjacent elements |
| Greedy without proof | Wrong answer on edge cases | Verify with exchange argument |
| Shrinking window when non-shrinkable needed | Incorrect answer | Identify which variant applies |
| Missing base case in backtracking | Infinite recursion | Always check termination first |
Exercises
- Sliding Window: Find the minimum window substring containing all characters of a target string
- Two Pointers: Given a sorted array, find the number of pairs with difference exactly k
- Binary Search on Answer: Given n books with pages[i], distribute among k students minimizing maximum pages
- Greedy: Given arrival/departure times, find the minimum number of platforms needed at a station
- Backtracking: Generate all valid parentheses combinations for n pairs
Process
- Gather information. Ask the user clarifying questions to understand their specific situation, goals, and constraints
- Analyze context. Review the information provided and identify key factors relevant to algorithm pattern master
- Develop recommendations. Apply domain expertise to create actionable guidance tailored to the user's needs
- Present structured output. Deliver findings in the output format below with clear next steps
- Address follow-ups. Answer additional questions and refine recommendations based on feedback
Output Format
## Algorithm Pattern Master Analysis
### Assessment
[Key findings and observations]
### Recommendations
1. [Primary recommendation]
2. [Secondary recommendation]
3. [Additional suggestions]
### Action Items
- [ ] [First action step]
- [ ] [Second action step]
- [ ] [Follow-up task]
Edge Cases
- Incomplete information: Ask clarifying questions before proceeding with recommendations
- Conflicting requirements: Prioritize the most critical constraint and note trade-offs
- Out of scope requests: Redirect to appropriate specialized skill or professional resource
- Beginner vs advanced: Adjust depth and terminology based on user's experience level
Example
Input: "Help me with algorithm pattern master for my current situation"
Output:
Based on your situation, here is a structured approach to algorithm pattern master:
- Assessment: Evaluate your current state and identify key areas for improvement
- Strategy: Develop a targeted plan based on best practices
- Implementation: Execute the plan with specific, measurable steps
- Review: Monitor progress and adjust as needed