Find the Largest divisor Subset in the Array
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 = 0
Input: 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++
#include <bits/stdc++.h>
using namespace std;
void findSubSeq( int arr[], int n)
{
sort(arr, arr + n);
int count[n] = { 1 };
int prev[n] = { -1 };
memset (count, 1, sizeof (count));
memset (prev, -1, sizeof (prev));
int max = 0;
int maxprev = -1;
for ( int i = 0; i < n; i++) {
for ( int j = i - 1; j >= 0; j--) {
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
count[i] = count[j] + 1;
prev[i] = j;
}
}
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
int i = maxprev;
while (i >= 0) {
if (arr[i] != -1)
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;
}
|
Java
import java.util.*;
class GFG
{
static void findSubSeq( int arr[], int n)
{
Arrays.sort(arr);
int count[] = new int [n];
int prev[] = new int [n];
int i, j;
for (i = 0 ; i < n; i++)
count[i] = 1 ;
for (j = 0 ; j < n; j++)
prev[j] = - 1 ;
int max = 0 ;
int maxprev = - 1 ;
for ( i = 0 ; i < n; i++)
{
for ( j = i - 1 ; j >= 0 ; j--)
{
if (arr[i] % arr[j] == 0 &&
count[j] + 1 > count[i])
{
count[i] = count[j] + 1 ;
prev[i] = j;
}
}
if (max < count[i])
{
max = count[i];
maxprev = i;
}
}
i = maxprev;
while (i >= 0 )
{
if (arr[i] != - 1 )
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);
}
}
|
Python3
def findSubSeq(arr, n) :
arr.sort();
count = [ 1 ] * n;
prev = [ - 1 ] * n;
max = 0 ;
maxprev = - 1 ;
for i in range (n) :
for j in range (i - 1 , - 1 , - 1 ) :
if (arr[i] % arr[j] = = 0 and
count[j] + 1 > count[i]) :
count[i] = count[j] + 1 ;
prev[i] = j;
if ( max < count[i]) :
max = count[i];
maxprev = i;
i = maxprev;
while (i > = 0 ) :
if (arr[i] ! = - 1 ) :
print (arr[i], end = " " );
i = prev[i];
if __name__ = = "__main__" :
arr = [ 1 , 2 , 3 , 4 , 5 ];
n = len (arr);
findSubSeq(arr, n);
|
C#
using System;
using System.Collections;
class GFG
{
static void findSubSeq( int []arr, int n)
{
Array.Sort(arr);
int []count = new int [n];
int []prev = new int [n];
int i, j;
for (i = 0; i < n; i++)
count[i] = 1;
for (j = 0; j < n; j++)
prev[j] = -1;
int max = 0;
int maxprev = -1;
for ( i = 0; i < n; i++)
{
for ( j = i - 1; j >= 0; j--)
{
if (arr[i] % arr[j] == 0 &&
count[j] + 1 > count[i])
{
count[i] = count[j] + 1;
prev[i] = j;
}
}
if (max < count[i])
{
max = count[i];
maxprev = i;
}
}
i = maxprev;
while (i >= 0)
{
if (arr[i] != -1)
Console.Write(arr[i] + " " );
i = prev[i];
}
}
public static void Main ()
{
int []arr = { 1, 2, 3, 4, 5 };
int n = arr.Length;
findSubSeq(arr, n);
}
}
|
Javascript
<script>
function findSubSeq(arr, n)
{
arr.sort();
var count = new Array(n);
var prev = new Array(n);
count.fill(1);
prev.fill(-1);
var max = 0;
var maxprev = -1;
for ( var i = 0; i < n; i++) {
for ( var j = i - 1; j >= 0; j--) {
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
count[i] = count[j] + 1;
prev[i] = j;
}
}
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
var i = maxprev;
while (i >= 0) {
if (arr[i] != -1)
document.write( arr[i] + " " );
i = prev[i];
}
}
var arr = [ 1, 2, 3, 4, 5 ];
var n = arr.length;
findSubSeq(arr, n);
</script>
|
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:
C++
#include <bits/stdc++.h>
using namespace std;
void findSubSeq( int arr[], int n) {
sort(arr, arr + n);
int count[n] = { 1 };
int prev[n] = { -1 };
memset (count, 1, sizeof (count));
memset (prev, -1, sizeof (prev));
int max = 0;
int maxprev = -1;
for ( int i = 0; i < n; i++) {
for ( int j = i - 1; j >= 0; j--) {
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
count[i] = count[j] + 1;
prev[i] = j;
}
}
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
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;
}
|
Java
import java.util.Arrays;
public class FindSubSeq {
public static void findSubSeq( int [] arr, int n) {
Arrays.sort(arr);
int [] count = new int [n];
int [] prev = new int [n];
Arrays.fill(count, 1 );
Arrays.fill(prev, - 1 );
int max = 0 ;
int maxprev = - 1 ;
for ( int i = 0 ; i < n; i++) {
for ( int j = i - 1 ; j >= 0 ; j--) {
if (arr[i] % arr[j] == 0
&& count[j] + 1 > count[i]) {
count[i] = count[j] + 1 ;
prev[i] = j;
}
}
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
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);
}
}
|
Python3
def findSubSeq(arr, n):
arr.sort()
count = [ 1 ] * n
prev = [ - 1 ] * n
max = 0
maxprev = - 1
for i in range (n):
for j in range (i - 1 , - 1 , - 1 ):
if arr[i] % arr[j] = = 0 and count[j] + 1 > count[i]:
count[i] = count[j] + 1
prev[i] = j
if max < count[i]:
max = count[i]
maxprev = i
i = maxprev
while i > = 0 :
print (arr[i], end = " " )
i = prev[i]
arr = [ 1 , 2 , 3 , 4 , 5 ]
n = len (arr)
findSubSeq(arr, n)
|
C#
using System;
class GFG
{
static void FindSubsequence( int [] arr, int n)
{
Array.Sort(arr);
int [] count = new int [n];
int [] prev = new int [n];
Array.Fill(count, 1);
Array.Fill(prev, -1);
int max = 0;
int maxprev = -1;
for ( int i = 0; i < n; i++)
{
for ( int j = i - 1; j >= 0; j--)
{
if (arr[i] % arr[j] == 0 && count[j] + 1 > count[i])
{
count[i] = count[j] + 1;
prev[i] = j;
}
}
if (max < count[i])
{
max = count[i];
maxprev = i;
}
}
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);
}
}
|
Javascript
function findSubSeq(arr) {
const n = arr.length;
arr.sort((a, b) => a - b);
const count = new Array(n).fill(1);
const prev = new Array(n).fill(-1);
let max = 0;
let maxprev = -1;
for (let i = 0; i < n; i++) {
for (let j = i - 1; j >= 0; j--) {
if (arr[i] % arr[j] === 0 && count[j] + 1 > count[i]) {
count[i] = count[j] + 1;
prev[i] = j;
}
}
if (max < count[i]) {
max = count[i];
maxprev = i;
}
}
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);
|
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.
Last Updated :
18 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...