You are given an array of n distinct positive integers, arr[]. Your goal is to determine the size of the largest subset of arr[] in which, for every pair of elements in the subset, the larger element is divisible by the smaller element.
Examples:
Input: arr[] = [10, 5, 3, 15, 20]
Output: 3
Explanation: The subset {5, 10, 20} is of maximum size, because for every pair of elements in it, the larger number is divisible by the smaller number.Input: arr[] = [18, 1, 3, 6, 13, 17]
Output: 4
Explanation: The subset {18, 1, 3, 6} is of maximum size, because for every pair of elements in it, the larger number is divisible by the smaller number.
Table of Content
[Naive Approach] - Generating All Subsets - O((2 ^ n) * (n ^ 2)) Time and O(1) Space
The idea is to generate all possible subsets of the given array arr[], and for each subset check if it follows the given condition, if so, update the length of maximum such subset found.
Follow the below given steps:
- Initialize
resto 0 and start with an emptycur[]. - Begin the recursion at index
ind = 0. - At each recursive step:
- If
indequals the length ofarr[]:- Check every pair in
cur[]; if for any pair the larger element isn’t divisible by the smaller, treat it as invalid. - If all pairs pass, set
res = max(res, cur.size()). - Return to explore other subsets.
- Check every pair in
- Otherwise:
- Add
arr[ind]tocur[], recurse withind + 1, then remove it fromcur[]. - Recurse with
ind + 1without adding the current element.
- Add
- If
- After all recursive calls finish,
reswill hold the length of the largest divisible subset.
#include <bits/stdc++.h>
using namespace std;
// function to check for all the pairs, if
// smaller element divides the larger element
bool divisible(vector<int> &arr) {
int n = arr.size();
// check for all the pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// if smaller element divides the larger element
if ((arr[i] > arr[j] && arr[i] % arr[j] != 0) ||
(arr[j] > arr[i] && arr[j] % arr[i] != 0)) {
return false;
}
}
}
return true;
}
// recursive function generate all subsets
void subsets(int ind, vector<int> &arr, vector<int> &cur, int &res) {
int n = arr.size();
// base case, if end index is reached
if (ind == n) {
// check for all the pairs, if smaller
// element divides the larger element
if(divisible(cur)) {
// update the result
res = max(res, (int)cur.size());
}
return;
}
// include the current element
cur.push_back(arr[ind]);
subsets(ind + 1, arr, cur, res);
cur.pop_back();
// exclude the current element
subsets(ind + 1, arr, cur, res);
}
int largestSubset(vector<int> &arr) {
// to store the result
int res = 0;
// to store current subset
vector<int> cur;
// function to generate subsets
subsets(0, arr, cur, res);
return res;
}
int main() {
vector<int> arr = {10, 5, 3, 15, 20};
cout << largestSubset(arr);
return 0;
}
import java.util.*;
public class GfG {
// function to check for all the pairs, if
// smaller element divides the larger element
public static boolean divisible(List<Integer> arr) {
int n = arr.size();
// check for all the pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// if smaller element divides the larger element
if ((arr.get(i) > arr.get(j) &&
arr.get(i) % arr.get(j) != 0) ||
(arr.get(j) > arr.get(i) &&
arr.get(j) % arr.get(i) != 0)) {
return false;
}
}
}
return true;
}
// recursive function generate all subsets
public static void subsets(int ind, List<Integer> arr, List<Integer> cur, int[] res) {
int n = arr.size();
// base case, if end index is reached
if (ind == n) {
// check for all the pairs, if smaller
// element divides the larger element
if (divisible(cur)) {
// update the result
res[0] = Math.max(res[0], cur.size());
}
return;
}
// include the current element
cur.add(arr.get(ind));
subsets(ind + 1, arr, cur, res);
cur.remove(cur.size() - 1);
// exclude the current element
subsets(ind + 1, arr, cur, res);
}
public static int largestSubset(List<Integer> arr) {
// to store the result
int[] res = {0};
// to store current subset
List<Integer> cur = new ArrayList<>();
// function to generate subsets
subsets(0, arr, cur, res);
return res[0];
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(10, 5, 3, 15, 20);
System.out.println(largestSubset(arr));
}
}
# function to check for all the pairs, if
# smaller element divides the larger element
def divisible(arr):
n = len(arr)
# check for all the pairs
for i in range(n):
for j in range(i + 1, n):
# if smaller element divides the larger element
if (arr[i] > arr[j] and arr[i] % arr[j] != 0) or \
(arr[j] > arr[i] and arr[j] % arr[i] != 0):
return False
return True
# recursive function generate all subsets
def subsets(ind, arr, cur, res):
n = len(arr)
# base case, if end index is reached
if ind == n:
# check for all the pairs, if smaller
# element divides the larger element
if divisible(cur):
# update the result
res[0] = max(res[0], len(cur))
return
# include the current element
cur.append(arr[ind])
subsets(ind + 1, arr, cur, res)
cur.pop()
# exclude the current element
subsets(ind + 1, arr, cur, res)
def largestSubset(arr):
# to store the result
res = [0]
# to store current subset
cur = []
# function to generate subsets
subsets(0, arr, cur, res)
return res[0]
if __name__ == "__main__":
arr = [10, 5, 3, 15, 20]
print(largestSubset(arr))
using System;
using System.Collections.Generic;
public class GfG {
// function to check for all the pairs, if
// smaller element divides the larger element
public static bool divisible(List<int> arr) {
int n = arr.Count;
// check for all the pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// if smaller element divides the larger element
if ((arr[i] > arr[j] && arr[i] % arr[j] != 0) ||
(arr[j] > arr[i] && arr[j] % arr[i] != 0)) {
return false;
}
}
}
return true;
}
// recursive function generate all subsets
public static void subsets(int ind, List<int> arr,
List<int> cur, ref int res) {
int n = arr.Count;
// base case, if end index is reached
if (ind == n) {
// check for all the pairs, if smaller
// element divides the larger element
if (divisible(cur)) {
// update the result
res = Math.Max(res, cur.Count);
}
return;
}
// include the current element
cur.Add(arr[ind]);
subsets(ind + 1, arr, cur, ref res);
cur.RemoveAt(cur.Count - 1);
// exclude the current element
subsets(ind + 1, arr, cur, ref res);
}
public static int largestSubset(List<int> arr) {
// to store the result
int res = 0;
// to store current subset
List<int> cur = new List<int>();
// function to generate subsets
subsets(0, arr, cur, ref res);
return res;
}
public static void Main() {
List<int> arr = new List<int> { 10, 5, 3, 15, 20 };
Console.WriteLine(largestSubset(arr));
}
}
// function to check for all the pairs, if
// smaller element divides the larger element
function divisible(arr) {
const n = arr.length;
// check for all the pairs
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// if smaller element divides the larger element
if ((arr[i] > arr[j] && arr[i] % arr[j] !== 0) ||
(arr[j] > arr[i] && arr[j] % arr[i] !== 0)) {
return false;
}
}
}
return true;
}
// recursive function generate all subsets
function subsets(ind, arr, cur, res) {
const n = arr.length;
// base case, if end index is reached
if (ind === n) {
// check for all the pairs, if smaller
// element divides the larger element
if (divisible(cur)) {
// update the result
res.value = Math.max(res.value, cur.length);
}
return;
}
// include the current element
cur.push(arr[ind]);
subsets(ind + 1, arr, cur, res);
cur.pop();
// exclude the current element
subsets(ind + 1, arr, cur, res);
}
function largestSubset(arr) {
// to store the result
const res = { value: 0 };
// to store current subset
const cur = [];
// function to generate subsets
subsets(0, arr, cur, res);
return res.value;
}
const arr = [10, 5, 3, 15, 20];
console.log(largestSubset(arr));
Output
3
[Expected Approach] - Using Sorting and Tabulation - O(n ^ 2) Time and O(n) Space
The idea is to sort the input array so that for any element at index i, all its potential multiples appear to its right. Traversing from the last index down to zero, a DP array dp[] is constructed where dp[i] stores the size of the largest divisible subset with arr[i] as its smallest element. For each i, the maximum dp[j] among all j > i with arr[j] % arr[i] == 0 is identified (mxm), and dp[i] is set to 1 + mxm. A variable res tracks the overall maximum in dp[] and is returned at the end.
Follow the below given steps:
- Sort arr[] in ascending order.
- Initialize res to 0 and create a array dp[] of length n.
- For i from n -  1 down to 0:
- Set mxm to 0
- For each j from i + 1 to n  - 1:
- If arr[j] % arr[i] == 0, update mxm = max(mxm, dp[j])
- Assign dp[i] = 1 + mxm
- Update res = max(res, dp[i])
- Return res
Below is given the implementation:
#include <bits/stdc++.h>
using namespace std;
int largestSubset(vector<int> &arr) {
int n = arr.size();
// sort the given array
sort(arr.begin(), arr.end());
// to store the result
int res = 0;
// initialize the dp array
vector<int> dp(n);
// fill the smaller values
for(int i = n - 1; i >= 0; i--) {
// find multiples of arr[i], and
// store one with largest subset
int mxm = 0;
for(int j = i + 1; j < n; j++) {
if(arr[j] % arr[i] == 0)
mxm = max(mxm, dp[j]);
}
dp[i] = 1 + mxm;
res = max(res, dp[i]);
}
return res;
}
int main() {
vector<int> arr = {10, 5, 3, 15, 20};
cout << largestSubset(arr);
return 0;
}
import java.util.*;
public class GfG {
public static int largestSubset(List<Integer> arr) {
int n = arr.size();
// sort the given array
Collections.sort(arr);
// to store the result
int res = 0;
// initialize the dp array
int[] dp = new int[n];
// fill the smaller values
for (int i = n - 1; i >= 0; i--) {
// find multiples of arr[i], and
// store one with largest subset
int mxm = 0;
for (int j = i + 1; j < n; j++) {
if (arr.get(j) % arr.get(i) == 0)
mxm = Math.max(mxm, dp[j]);
}
dp[i] = 1 + mxm;
res = Math.max(res, dp[i]);
}
return res;
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(10, 5, 3, 15, 20);
System.out.println(largestSubset(arr));
}
}
def largestSubset(arr):
n = len(arr)
# sort the given array
arr.sort()
# to store the result
res = 0
# initialize the dp array
dp = [0] * n
# fill the smaller values
for i in range(n - 1, -1, -1):
# find multiples of arr[i], and
# store one with largest subset
mxm = 0
for j in range(i + 1, n):
if arr[j] % arr[i] == 0:
mxm = max(mxm, dp[j])
dp[i] = 1 + mxm
res = max(res, dp[i])
return res
if __name__ == "__main__":
arr = [10, 5, 3, 15, 20]
print(largestSubset(arr))
using System;
using System.Collections.Generic;
public class GfG {
public static int largestSubset(List<int> arr) {
int n = arr.Count;
// sort the given array
arr.Sort();
// to store the result
int res = 0;
// initialize the dp array
int[] dp = new int[n];
// fill the smaller values
for (int i = n - 1; i >= 0; i--) {
// find multiples of arr[i], and
// store one with largest subset
int mxm = 0;
for (int j = i + 1; j < n; j++) {
if (arr[j] % arr[i] == 0)
mxm = Math.Max(mxm, dp[j]);
}
dp[i] = 1 + mxm;
res = Math.Max(res, dp[i]);
}
return res;
}
public static void Main() {
List<int> arr = new List<int> { 10, 5, 3, 15, 20 };
Console.WriteLine(largestSubset(arr));
}
}
function largestSubset(arr) {
const n = arr.length;
// sort the given array
arr.sort((a, b) => a - b);
// to store the result
let res = 0;
// initialize the dp array
const dp = Array(n).fill(0);
// fill the smaller values
for (let i = n - 1; i >= 0; i--) {
// find multiples of arr[i], and
// store one with largest subset
let mxm = 0;
for (let j = i + 1; j < n; j++) {
if (arr[j] % arr[i] === 0)
mxm = Math.max(mxm, dp[j]);
}
dp[i] = 1 + mxm;
res = Math.max(res, dp[i]);
}
return res;
}
const arr = [10, 5, 3, 15, 20];
console.log(largestSubset(arr));
Output
3