Given an array arr[] of N integers, the task is to find the largest subset of arr[] such that in every pair of numbers from that subset, one number is a divisor of the other.
Examples:
Input: arr[] = {1, 2, 3, 4, 5}
Output: 4 2 1
All possible pairs of the subsequence are:
(4, 2) -> 4 % 2 = 0
(4, 1) -> 4 % 1 = 0
and (2, 1) -> 2 % 1 = 0Input: arr[] = {1, 3, 4, 9}
Output: 1 3 9
Approach: Here the task is to find the largest subset where in every pair of numbers, one is divisible by the other i.e. for the sequence a1, a2, a3 … ak where a1 ≤ a2 ≤ … ≤ ak and ai+1 % ai = 0 for every i. This sequence can be found using dynamic programming (similar to longest increasing subsequence).
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std;
// Function to find the required subsequence void findSubSeq( int arr[], int n)
{ // Sort the array
sort(arr, arr + n);
// Keep a count of the length of the
// subsequence and the previous element
int count[n] = { 1 };
int prev[n] = { -1 };
// Set the initial values
memset (count, 1, sizeof (count));
memset (prev, -1, sizeof (prev));
// Maximum length of the subsequence and
// the last element
int max = 0;
int maxprev = -1;
// Run a loop for every element
for ( int i = 0; i < n; i++) {
// Check for all the divisors
for ( int j = i - 1; j >= 0; j--) {
// If the element is a divisor and the length
// of subsequence will increase by adding
// j as previous element of i
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
// Increase the count
count[i] = count[j] + 1;
prev[i] = j;
}
}
// Update the max count
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
// Get the last index of the subsequence
int i = maxprev;
while (i >= 0) {
// Print the element
if (arr[i] != -1)
cout << arr[i] << " " ;
// Move the index to the previous element
i = prev[i];
}
} // Driver code int main()
{ int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof (arr) / sizeof ( int );
findSubSeq(arr, n);
return 0;
} |
// Java implementation of the approach import java.util.*;
class GFG
{ // Function to find the required subsequence
static void findSubSeq( int arr[], int n)
{
// Sort the array
Arrays.sort(arr);
// Keep a count of the length of the
// subsequence and the previous element
int count[] = new int [n];
int prev[] = new int [n];
int i, j;
// Set the initial values
for (i = 0 ; i < n; i++)
count[i] = 1 ;
for (j = 0 ; j < n; j++)
prev[j] = - 1 ;
// Maximum length of the subsequence and
// the last element
int max = 0 ;
int maxprev = - 1 ;
// Run a loop for every element
for ( i = 0 ; i < n; i++)
{
// Check for all the divisors
for ( j = i - 1 ; j >= 0 ; j--)
{
// If the element is a divisor and
// the length of subsequence will
// increase by adding j as
// previous element of i
if (arr[i] % arr[j] == 0 &&
count[j] + 1 > count[i])
{
// Increase the count
count[i] = count[j] + 1 ;
prev[i] = j;
}
}
// Update the max count
if (max < count[i])
{
max = count[i];
maxprev = i;
}
}
// Get the last index of the subsequence
i = maxprev;
while (i >= 0 )
{
// Print the element
if (arr[i] != - 1 )
System.out.print(arr[i] + " " );
// Move the index to the previous element
i = prev[i];
}
}
// Driver code
public static void main (String[] args)
{
int arr[] = { 1 , 2 , 3 , 4 , 5 };
int n = arr.length;
findSubSeq(arr, n);
}
} // This code is contributed by AnkitRai01 |
# Python3 implementation of the approach # Function to find the required subsequence def findSubSeq(arr, n) :
# Sort the array
arr.sort();
# Keep a count of the length of the
# subsequence and the previous element
# Set the initial values
count = [ 1 ] * n;
prev = [ - 1 ] * n;
# Maximum length of the subsequence and
# the last element
max = 0 ;
maxprev = - 1 ;
# Run a loop for every element
for i in range (n) :
# Check for all the divisors
for j in range (i - 1 , - 1 , - 1 ) :
# If the element is a divisor and the length
# of subsequence will increase by adding
# j as previous element of i
if (arr[i] % arr[j] = = 0 and
count[j] + 1 > count[i]) :
# Increase the count
count[i] = count[j] + 1 ;
prev[i] = j;
# Update the max count
if ( max < count[i]) :
max = count[i];
maxprev = i;
# Get the last index of the subsequence
i = maxprev;
while (i > = 0 ) :
# Print the element
if (arr[i] ! = - 1 ) :
print (arr[i], end = " " );
# Move the index to the previous element
i = prev[i];
# Driver code if __name__ = = "__main__" :
arr = [ 1 , 2 , 3 , 4 , 5 ];
n = len (arr);
findSubSeq(arr, n);
# This code is contributed by AnkitRai01 |
// C# implementation of the approach using System;
using System.Collections;
class GFG
{ // Function to find the required subsequence
static void findSubSeq( int []arr, int n)
{
// Sort the array
Array.Sort(arr);
// Keep a count of the length of the
// subsequence and the previous element
int []count = new int [n];
int []prev = new int [n];
int i, j;
// Set the initial values
for (i = 0; i < n; i++)
count[i] = 1;
for (j = 0; j < n; j++)
prev[j] = -1;
// Maximum length of the subsequence
// and the last element
int max = 0;
int maxprev = -1;
// Run a loop for every element
for ( i = 0; i < n; i++)
{
// Check for all the divisors
for ( j = i - 1; j >= 0; j--)
{
// If the element is a divisor and
// the length of subsequence will
// increase by adding j as
// previous element of i
if (arr[i] % arr[j] == 0 &&
count[j] + 1 > count[i])
{
// Increase the count
count[i] = count[j] + 1;
prev[i] = j;
}
}
// Update the max count
if (max < count[i])
{
max = count[i];
maxprev = i;
}
}
// Get the last index of the subsequence
i = maxprev;
while (i >= 0)
{
// Print the element
if (arr[i] != -1)
Console.Write(arr[i] + " " );
// Move the index to the previous element
i = prev[i];
}
}
// Driver code
public static void Main ()
{
int []arr = { 1, 2, 3, 4, 5 };
int n = arr.Length;
findSubSeq(arr, n);
}
} // This code is contributed by AnkitRai01 |
<script> // Javascript implementation of above approach // Function to find the required subsequence function findSubSeq(arr, n)
{ // Sort the array
arr.sort();
// Keep a count of the length of the
// subsequence and the previous element
var count = new Array(n);
var prev = new Array(n);
// Set the initial values
count.fill(1);
prev.fill(-1);
// Maximum length of the subsequence and
// the last element
var max = 0;
var maxprev = -1;
// Run a loop for every element
for ( var i = 0; i < n; i++) {
// Check for all the divisors
for ( var j = i - 1; j >= 0; j--) {
// If the element is a divisor and the length
// of subsequence will increase by adding
// j as previous element of i
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
// Increase the count
count[i] = count[j] + 1;
prev[i] = j;
}
}
// Update the max count
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
// Get the last index of the subsequence
var i = maxprev;
while (i >= 0) {
// Print the element
if (arr[i] != -1)
document.write( arr[i] + " " );
// Move the index to the previous element
i = prev[i];
}
} var arr = [ 1, 2, 3, 4, 5 ];
var n = arr.length;
findSubSeq(arr, n); //This code is contributed by SoumikMondal </script> |
4 2 1
Time Complexity: O(N2), where N is the length of the given array.
Auxiliary Space: O(N)
Approach(Dynamic programming):
The approach uses dynamic programming to find the largest subset of an array such that in every pair of numbers from that subset, one number is a divisor of the other. It initializes a dp array with 1’s as the minimum size of a subset is 1. It then iterates over each element in the array and checks for all its divisors if there is a larger subset ending at that divisor index. If a larger subset is found, it updates the dp[i] with the new maximum value. Finally, it returns the largest subset by backtracking through the dp array.
here’s the full implementation of the code:
#include <bits/stdc++.h> using namespace std;
void findSubSeq( int arr[], int n) {
// Sort the array
sort(arr, arr + n);
// Keep a count of the length of the
// subsequence and the previous element
int count[n] = { 1 };
int prev[n] = { -1 };
// Set the initial values
memset (count, 1, sizeof (count));
memset (prev, -1, sizeof (prev));
// Maximum length of the subsequence and
// the last element
int max = 0;
int maxprev = -1;
// Run a loop for every element
for ( int i = 0; i < n; i++) {
// Check for all the divisors
for ( int j = i - 1; j >= 0; j--) {
// If the element is a divisor and the length
// of subsequence will increase by adding
// j as previous element of i
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
// Increase the count
count[i] = count[j] + 1;
prev[i] = j;
}
}
// Update the max count
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
// Print the largest divisor subset in reverse order
int i = maxprev;
while (i >= 0) {
cout << arr[i] << " " ;
i = prev[i];
}
} int main() {
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof (arr) / sizeof ( int );
findSubSeq(arr, n);
return 0;
} |
import java.util.Arrays;
public class FindSubSeq {
public static void findSubSeq( int [] arr, int n) {
// Sort the array
Arrays.sort(arr);
// Keep a count of the length of the
// subsequence and the previous element
int [] count = new int [n];
int [] prev = new int [n];
// Set the initial values
Arrays.fill(count, 1 );
Arrays.fill(prev, - 1 );
// Maximum length of the subsequence and
// the last element
int max = 0 ;
int maxprev = - 1 ;
// Run a loop for every element
for ( int i = 0 ; i < n; i++) {
// Check for all the divisors
for ( int j = i - 1 ; j >= 0 ; j--) {
// If the element is a divisor and the length
// of subsequence will increase by adding
// j as previous element of i
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
// Increase the count
count[i] = count[j] + 1 ;
prev[i] = j;
}
}
// Update the max count
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
// Print the largest divisor subset in reverse order
int i = maxprev;
while (i >= 0 ) {
System.out.print(arr[i] + " " );
i = prev[i];
}
}
public static void main(String[] args) {
int arr[] = { 1 , 2 , 3 , 4 , 5 };
int n = arr.length;
findSubSeq(arr, n);
}
} |
def findSubSeq(arr, n):
# Sort the array
arr.sort()
# Keep a count of the length of the subsequence and the previous element
count = [ 1 ] * n
prev = [ - 1 ] * n
# Maximum length of the subsequence and the last element
max = 0
maxprev = - 1
# Run a loop for every element
for i in range (n):
# Check for all the divisors
for j in range (i - 1 , - 1 , - 1 ):
# If the element is a divisor and the length of subsequence will increase by adding j as previous element of i
if arr[i] % arr[j] = = 0 and count[j] + 1 > count[i]:
# Increase the count
count[i] = count[j] + 1
prev[i] = j
# Update the max count
if max < count[i]:
max = count[i]
maxprev = i
# Print the largest divisor subset in reverse order
i = maxprev
while i > = 0 :
print (arr[i], end = " " )
i = prev[i]
arr = [ 1 , 2 , 3 , 4 , 5 ]
n = len (arr)
findSubSeq(arr, n) |
using System;
class GFG
{ static void FindSubsequence( int [] arr, int n)
{
// Sort the array
Array.Sort(arr);
// Arrays to store the count of elements in the
// subsequence and their previous element indices
int [] count = new int [n];
int [] prev = new int [n];
// Initialize the count and previous arrays with default values
Array.Fill(count, 1);
Array.Fill(prev, -1);
// Variables to keep track of the maximum length of the
// subsequence and its last element's index
int max = 0;
int maxprev = -1;
// Loop for each element in the array
for ( int i = 0; i < n; i++)
{
// Check for all elements before the current element
for ( int j = i - 1; j >= 0; j--)
{
// If arr[i] is divisible by arr[j] and the subsequence will
// be longer by adding j as the previous element of i
if (arr[i] % arr[j] == 0 && count[j] + 1 > count[i])
{
// Update the count and previous element index
count[i] = count[j] + 1;
prev[i] = j;
}
}
// Update the maximum count and the index of the last element
// in the longest subsequence
if (max < count[i])
{
max = count[i];
maxprev = i;
}
}
// Print the largest divisor subset in reverse order
int idx = maxprev;
while (idx >= 0)
{
Console.Write(arr[idx] + " " );
idx = prev[idx];
}
}
static void Main()
{
int [] arr = { 1, 2, 3, 4, 5 };
int n = arr.Length;
FindSubsequence(arr, n);
}
} |
function findSubSeq(arr) {
const n = arr.length;
// Sort the array
arr.sort((a, b) => a - b);
// Keep a count of the length of the subsequence and the previous element
const count = new Array(n).fill(1);
const prev = new Array(n).fill(-1);
// Maximum length of the subsequence and the last element
let max = 0;
let maxprev = -1;
// Run a loop for every element
for (let i = 0; i < n; i++) {
// Check for all the divisors
for (let j = i - 1; j >= 0; j--) {
// If the element is a divisor and the length of subsequence will increase
// by adding j as the previous element of i
if (arr[i] % arr[j] === 0 && count[j] + 1 > count[i]) {
// Increase the count
count[i] = count[j] + 1;
prev[i] = j;
}
}
// Update the max count
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
// Print the largest divisor subset in order
let result = [];
let i = maxprev;
while (i >= 0) {
result.push(arr[i]);
i = prev[i];
}
console.log(result.join( " " ));
} const arr = [1, 2, 3, 4, 5]; findSubSeq(arr); |
4 2 1
Time Complexity: O(n^2) due to the nested loops used to check all possible divisors.
Auxiliary Space: O(n) to store the count and prev arrays.