Largest Divisible Subset
Sort the numbers. Let len[i] be the size of the largest valid group whose largest number is nums[i]. For each earlier j, if nums[i] % nums[j] == 0, the group ending at nums[j] can be extended by nums[i]. Keep the best one, and store its parent j. Walking the parents back from the best end gives the group.
A group is valid when each number divides the next one. Divisibility passes along a chain (if a | b and b | c, then a | c), so every pair in the group divides one way round.
Problem
You get a list of distinct positive whole numbers. Pick the largest group you can from the list, where every two numbers in the group have one that divides the other.
Return any group of the largest size. The order of the numbers in the answer does not matter.
nums, a list of distinct positive whole numbers. The list is not sorted.
A largest group of numbers from nums where every pair has one number dividing the other.
[1, 3] is also accepted. 2 and 3 do not divide each other, so they cannot both be in the group.
Each number divides the next one, so all four numbers fit in the group.
- • 1 ≤ nums.length ≤ 1000
- • 1 ≤ nums[i] ≤ 2 · 10^9
- • All the integers in nums are unique.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Can 2 and 3 both be in the group? What about 2 and 4? What is the rule for a pair?
- 2.
Does the order of the numbers in the list help me check the rule? What order would make it easier?
- 3.
If I know the best group that ends with a number x, how can I use it for a bigger number y?
- 4.
When I add y to a group, do I have to check y against every number already in the group, or is one check enough?
- 5.
I know the length of the best group. How do I get the actual numbers back?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Take or skip each number, then check every pair in each set | O(2^N · N^2) | O(N) |
| Optimal | Sort; len[i] is the best chain ending at nums[i]; keep parents and walk back | O(N^2) | O(N) |
Why does this belong to this pattern?
- “largest subset”We want a size. Keep the best size for each ending number, and take the maximum at the end.
- “every pair has one that divides the other”A group is a chain where each number is a multiple of the one before it. The state only needs the last number.
- “distinct positive numbers”No repeats, so each divisor is smaller than the number it divides. Sorting turns the list into a line we can scan.
This is LIS where the rule is divisibility instead of 'bigger'. In LIS, any bigger number can follow. Here a number can follow only when it is a multiple of the one before, which is a modulo test. The chain property is what makes the O(N²) loop correct: once the list is sorted, checking the last number of a chain is enough, and parent pointers rebuild the group.
Don't make this mistake
The loop only looks left, so a divisor placed after its multiple is never used. On [4, 2, 1], the loop never links 1 to 2 or 4, so it returns 1. The right answer is 3, the chain [1, 2, 4]. Sorting puts every divisor before the numbers it divides.
Dividing the smallest number is not enough to form a chain. On [1, 2, 3], every number is a multiple of 1, so this keeps all three. But 2 and 3 do not divide each other, so the right answer has size 2, for example [1, 2].
The best group does not have to end at the largest number. On [1, 2, 4, 8, 9], the chain ending at 9 is just [1, 9] (size 2). The best group is [1, 2, 4, 8] (size 4).
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like DP — Longest Increasing Subsequence translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.