Imagine you have a set of pairs representing tasks with start and end times, and you want to schedule the maximum number of non-overlapping tasks in a chain.
Given n pairs of numbers where each pair is of the form (a, b) and a < b, find the length of the longest chain which can be formed such that for every pair (c, d) that follows (a, b) in the chain, b < c. Return the length of the longest chain possible.
1 ≤ n ≤ 10^5-10^9 ≤ a < b ≤ 10^9
Edge cases: All pairs have the same start and end → output is 1Pairs are already sorted and non-overlapping → output is nPairs are in descending order → output is 1
def findLongestChain(pairs):
# Write your solution here
pass
class Solution {
public int findLongestChain(int[][] pairs) {
// Write your solution here
return 0;
}
}
#include <vector>
using namespace std;
int findLongestChain(vector<vector<int>>& pairs) {
// Write your solution here
return 0;
}
function findLongestChain(pairs) {
// Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: 3Using b <= c instead of strict b < c in chaining condition, allowing invalid chains.✅ Change condition to strictly b < c when checking if pairs can be chained.
Wrong: 2Greedy approach sorting by start time instead of end time, missing longer chains.✅ Sort pairs by their end time and greedily select pairs with start > last chosen end.
Wrong: 0Not handling empty input correctly, returning default 0 or error.✅ Add explicit check for empty input and return 0.
Wrong: 4Incorrectly counting multiple pairs with identical starts as chain.✅ Enforce strict chaining condition and proper sorting to avoid chaining pairs with same start.
Wrong: TLEUsing O(n^2) brute force or DP approach on large input.✅ Implement O(n log n) greedy solution sorting pairs by end time.
✓
Test Cases
Focus on base cases and boundary conditions like empty input and single pair.
Consider common algorithmic pitfalls such as greedy traps and handling identical starts.
Think about time complexity and how to optimize from quadratic to log-linear.
t1_01basic
Input{"pairs":[[1,2],[2,3],[3,4]]}
Expected2
⏱ Performance - must finish in 2000ms
The longest chain is [1,2] -> [3,4]. The pair [2,3] cannot be chained after [1,2] because 2 is not less than 2.
💡 Think about sorting pairs and then finding the longest increasing subsequence based on chain condition.
💡 Use dynamic programming or greedy approach sorting by pair end times to find max chain length.
💡 Sort pairs by their second element and greedily pick pairs where current start > last chosen end.
Why it failed: Output incorrect: likely failed to enforce strict b < c condition or incorrect sorting. Fix by sorting pairs by end time and only chaining pairs with start > previous end.
✓ Correctly computes longest chain length using proper sorting and chaining condition.
t1_02basic
Input{"pairs":[[5,24],[15,25],[27,40],[50,60]]}
Expected3
⏱ Performance - must finish in 2000ms
Longest chain is [5,24] -> [27,40] -> [50,60], length 3.
💡 Sort pairs by their end values to facilitate chaining.
💡 Check for pairs where current start is greater than last chosen pair's end.
💡 Greedy selection of pairs with earliest end time that can be chained.
Why it failed: Incorrect output: likely failed to sort by end or incorrectly compared pairs. Fix by sorting pairs by end and selecting pairs with start > last end.
✓ Correctly finds longest chain by sorting and chaining pairs.
t2_01edge
Input{"pairs":[]}
Expected0
⏱ Performance - must finish in 2000ms
Empty input means no pairs, so longest chain length is 0.
💡 Consider the base case when no pairs are given.
💡 Return 0 if input list is empty.
💡 Add a check for empty input and return 0 immediately.
Why it failed: Output not zero for empty input; fix by returning 0 when pairs list is empty.
✓ Handles empty input correctly by returning 0.
t2_02edge
Input{"pairs":[[1,2]]}
Expected1
⏱ Performance - must finish in 2000ms
Single pair forms a chain of length 1.
💡 Check behavior with only one pair.
💡 Longest chain with one pair is always 1.
💡 Return 1 if pairs length is 1.
Why it failed: Output not 1 for single pair input; fix by returning length 1 when only one pair exists.
✓ Correctly returns 1 for single pair input.
t2_03edge
Input{"pairs":[[1,2],[2,3],[3,4],[4,5]]}
Expected2
⏱ Performance - must finish in 2000ms
Pairs chain only if b < c; here consecutive pairs have b == c, so max chain length is 2 by skipping pairs.
💡 Check strict inequality b < c, not b <= c.
💡 Pairs with adjacent ends equal cannot be chained directly.
💡 Ensure chaining condition uses strict less than, not less or equal.
Why it failed: Output too large due to allowing b <= c; fix by enforcing strict b < c in chaining condition.
✓ Correctly enforces strict chaining condition b < c.
t3_01corner
Input{"pairs":[[1,10],[2,3],[4,5],[6,7],[8,9]]}
Expected4
⏱ Performance - must finish in 2000ms
Greedy by start time fails; correct longest chain is [2,3]->[4,5]->[6,7]->[8,9], length 4.
💡 Greedy by earliest start time can fail here.
💡 Try sorting by end time and greedily selecting pairs.
💡 Sort pairs by end and pick pairs with start > last chosen end.
Why it failed: Greedy by start time returns 2 instead of 4; fix by sorting pairs by end time and chaining accordingly. This is the greedy trap test.
✓ Correctly avoids greedy trap by sorting pairs by end time.
t3_02corner
Input{"pairs":[[1,2],[1,3],[1,4],[1,5]]}
Expected1
⏱ Performance - must finish in 2000ms
All pairs start at same point; only one can be chosen.
💡 Check handling of multiple pairs with same start.
💡 Longest chain is 1 since no pair can follow another.
💡 Ensure chaining condition strictly compares ends and starts.
Why it failed: Incorrectly counts multiple pairs as chain; fix by enforcing strict b < c condition and proper sorting. This is the identical start test.
✓ Correctly handles multiple pairs with identical starts.
t3_03corner
Input{"pairs":[[-10,-5],[-4,0],[1,5],[6,10]]}
Expected4
⏱ Performance - must finish in 2000ms
Pairs with negative and positive values chain fully: length 4.
💡 Check that negative values are handled correctly.
💡 Sorting and chaining logic should be value-agnostic.
💡 Ensure no assumptions about positive-only values in comparisons.
Why it failed: Fails on negative values due to incorrect comparisons; fix by using standard comparison operators without assumptions. This is the negative values test.
✓ Correctly handles pairs with negative and positive values.
t4_01performance
Input{"_description":"n=100000 at constraint boundary - executor generates this"}
Expectednull
⏱ Performance - must finish in 2000ms
n=100000, O(n log n) greedy approach must complete within 2 seconds.
💡 Brute force O(n^2) will time out for large n.
💡 Use greedy approach sorting by end time for O(n log n) complexity.
💡 Avoid nested loops; use single pass after sorting.
Why it failed: TLE due to O(n^2) or worse complexity; fix by implementing O(n log n) greedy solution sorting pairs by end time.
✓ Efficient O(n log n) solution passes within time limit.
Practice
(1/5)
1. Consider the following Fenwick Tree based code snippet for counting the number of longest increasing subsequences. Given the input array nums = [1, 3, 2], what is the final returned count of LIS?
easy
A. 2
B. 3
C. 1
D. 4
Solution
Step 1: Trace Fenwick tree updates for nums=[1,3,2]
For 1: query(0) -> (0,0), count=1, update(1,(1,1))
For 3: query(2) -> max_len=1,count=1, update(3,(2,1))
For 2: query(1) -> max_len=1,count=1, update(2,(2,1))
Step 2: Final query on full range
query(3) returns max_len=2, total_count=2 (from 3 and 2 updates), so total LIS count is 2.
Final Answer:
Option A -> Option A
Quick Check:
Two LIS: [1,2] and [1,3] [OK]
Hint: Count increments when length ties in Fenwick tree [OK]
Common Mistakes:
Off-by-one in Fenwick indexing
Forgetting to set count=1 when zero
Mixing length and count in update
2. What is the time complexity of the bottom-up bitmask DP solution for the shortest path visiting all nodes problem on a graph with n nodes?
medium
A. O(n * 2^n)
B. O(n^2 * 2^n)
C. O(n! * n)
D. O(2^n * E) where E is the number of edges
Solution
Step 1: Identify loops in the bottom-up DP
The outer loop iterates over all masks (2^n), the inner loop over nodes (n), and for each node, we iterate over its neighbors (E edges total). Thus, the complexity depends on the number of edges.
Step 2: Confirm complexity formula
Since each state dp[u][mask] is updated by checking neighbors, total complexity is O(2^n * E), where E is the number of edges.
Final Answer:
Option D -> Option D
Quick Check:
Matches known complexity for bitmask DP on graphs [OK]
Hint: Complexity depends on subsets and edges, not just nodes squared [OK]
Common Mistakes:
Confusing with O(n^2 * 2^n)
Ignoring neighbor iteration
Assuming factorial complexity
3. What is the time complexity of the bottom-up bitmask DP solution for the Travelling Salesman Problem with n cities, and why?
Options:
medium
A. O(n * 2^n) because we process each subset and city once
B. O(2^n) because subsets dominate the complexity
C. O(n^2 * 2^n) because for each subset and city, we check all possible previous cities
D. O(n! ) because we consider all permutations of cities
Solution
Step 1: Identify loops in the code
There are three nested loops: over all subsets (2^n), over all cities (n), and over all possible previous cities (n).
Step 2: Multiply loop complexities
Total complexity is O(2^n * n * n) = O(n^2 * 2^n). O(n * 2^n) because we process each subset and city once misses the inner loop over previous cities, underestimating complexity.
Final Answer:
Option C -> Option C
Quick Check:
Bitmask DP complexity is well-known as O(n^2 * 2^n) [OK]
Hint: Remember triple nested loops: subsets, current city, previous city [OK]
Common Mistakes:
Ignoring inner loop over previous cities leads to underestimation
4. Suppose the problem changes: now you want to count the number of longest increasing subsequences where elements can be reused multiple times (i.e., subsequences are non-strictly increasing and elements can appear multiple times). Which modification to the Fenwick tree based algorithm correctly handles this?
hard
A. Change the comparison in Fenwick tree queries to allow equal elements and update counts accordingly
B. Replace Fenwick tree with a segment tree that supports range maximum queries and counts for non-strictly increasing sequences
C. No change needed; the original algorithm already counts sequences with reuse
D. Use the same algorithm but double the counts at each update to account for reuse
Solution
Step 1: Understand reuse and non-strictly increasing requirement
Allowing reuse means subsequences can have equal elements and elements can be chosen multiple times, breaking strict increasing assumption.
Step 2: Why Fenwick tree needs modification
Fenwick tree queries rely on strictly increasing order and unique indices; to handle reuse and non-strict sequences, segment tree with range max and count queries is needed to correctly aggregate counts over ranges including equal elements.
Step 3: Evaluate options
Simply changing comparison or doubling counts is incorrect; original algorithm assumes strict increasing and no reuse.
Final Answer:
Option B -> Option B
Quick Check:
Segment tree supports flexible queries needed for reuse and non-strict sequences [OK]
Hint: Reuse breaks strict increasing; segment tree needed [OK]
Common Mistakes:
Assuming original Fenwick tree works
Trying to double counts naively
Ignoring non-strict condition
5. Suppose the Travelling Salesman Problem is modified so that cities can be visited multiple times (revisits allowed). Which of the following changes to the bottom-up bitmask DP approach correctly adapts to this variant?
hard
A. Remove the bitmask representing visited cities and use simple DP over current city and steps taken
B. Keep the bitmask DP as is, since revisits do not affect the visited set representation
C. Use a shortest path algorithm like Floyd-Warshall instead of DP
D. Modify the DP to track the count of visits per city in the state
Solution
Step 1: Understand revisits break bitmask usage
Bitmask DP relies on each city visited exactly once; revisits mean visited set is no longer sufficient to represent state.
Step 2: Adapt DP state to allow revisits
Removing bitmask and using DP over current city and number of steps (or path length) allows revisits, as visited set is not tracked.
Final Answer:
Option A -> Option A
Quick Check:
Bitmask DP is invalid if cities can be revisited [OK]
Hint: Bitmask DP encodes unique visits; revisits require different state [OK]
Common Mistakes:
Assuming bitmask DP works unchanged with revisits
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.