02
Chains and reconstruction (DP — Longest Increasing Subsequence Sub-pattern)
Same dp[i] = 1 + max dp[j], with a different "may come before" rule, and often a parent array to return the chain itself.
Signals in the problem statement
- ›
"largest divisible subset"
- ›
"word chain", "predecessor"
- ›
"wiggle" (up / down alternating)
- ›
"common increasing subsequence" of two arrays
What makes it different
Sort first when the rule needs an order (divisibility, word length). Some variants keep two states per element (wiggle: ending with a rise / with a fall).
Questions
ordered from “learn the idea” to “recognise it without help”- 1Largest Divisible SubsetWalkthroughMediumBasic Anchor·LeetCode #368
- 2Longest String ChainWalkthroughMediumSlight Variation·LeetCode #1048
- 3Wiggle SubsequenceWalkthroughMediumMedium·LeetCode #376
- 4Longest Common Increasing SubsequenceWalkthroughHardInterview-Level·GeeksforGeeks
Template
chain-template.cpp
// Longest chain with a custom "j may come before i" rule, returned as the actual chain.
// Shown for divisibility (Largest Divisible Subset); sort first so the rule only looks back.
vector<int> longestChain(vector<int> a) {
sort(a.begin(), a.end());
int n = a.size(), end = 0;
vector<int> dp(n, 1), parent(n, -1);
auto canFollow = [&](int j, int i) { return a[i] % a[j] == 0; };
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++)
if (canFollow(j, i) && dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; parent[i] = j; }
if (dp[i] > dp[end]) end = i;
}
vector<int> chain;
for (int i = n ? end : -1; i != -1; i = parent[i]) chain.push_back(a[i]); // walk back
reverse(chain.begin(), chain.end());
return chain;
}Remember this · DP — Longest Increasing Subsequence
Trigger
Longest chain where each item must be bigger/fit inside the previous one (numbers, pairs, envelopes, words).
Think
Does each element extend the best chain ending at some smaller earlier element?
Key question
Sort first? Then what does "increasing" mean for these items?