Make Binary Search Tree

Given an array arr[] of size N. The task is to find whether it is possible to make Binary Search Tree with the given array of elements such that greatest common divisor of any two vertices connected by a common edge is > 1. If possible then print Yes else print No.

Examples:

Input: arr[] = {3, 6, 9, 18, 36, 108}
Output: Yes

This is one of the possible Binary Search Tree with given array.

Input: arr[] = {2, 17}
Output: No



Approach: Let DP(l, r, root) be a DP determining whether it’s possible to assemble a tree rooted at root from the sub-segment [l..r].
It’s easy to see that calculating it requires extracting such rootleft from [l..root – 1] and rootright from [root + 1..right] such that:

  • gcd(aroot, arootleft) > 1
  • gcd(aroot, arootright) > 1
  • DP(l, root-1, rootleft) = 1
  • DP(root+1, r, rootright) = 1

This can be done in O(r – l) provided we are given all DP(x, y, z) values for all sub-segments of [l..r]. Considering a total of O(n3) DP states, the final complexity is O(n4) and that’s too much.

Let’s turn our DP into DPnew(l, r, state) where the state can be either 0 or 1. It immediately turns out that DP(l, r, root) is inherited from DPnew(l, root-1, 1) and DPnew(root+1, r, 0). Now we have O(n2) states, but at the same time, all transitions are performed in linear time. Thus final complexity is O(n3) which is sufficient to pass.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the appraoch
#include <bits/stdc++.h>
using namespace std;
  
// Maxium number of vertices
#define N 705
  
// To store is it possible at
// particular pace or not
int dp[N][N][2];
  
// Return 1 if from l to r, it is possible with
// the given state
int possibleWithState(int l, int r, int state, int a[])
{
    // Base condition
    if (l > r)
        return 1;
  
    // If it is already calculated
    if (dp[l][r][state] != -1)
        return dp[l][r][state];
  
    // Choose the root
    int root;
    if (state == 1)
        root = a[r + 1];
    else
        root = a[l - 1];
  
    // Traverse in range l to r
    for (int i = l; i <= r; i++) {
  
        // If gcd is greater than one
        // check for both sides
        if (__gcd(a[i], root) > 1) {
            int x = possibleWithState(l, i - 1, 1, a);
            if (x != 1)
                continue;
            int y = possibleWithState(i + 1, r, 0, a);
            if (x == 1 && y == 1)
                return dp[l][r][state] = 1;
        }
    }
  
    // If not possible
    return dp[l][r][state] = 0;
}
  
// Function that return true if it is possible
// to make Binary Search Tree
bool isPossible(int a[], int n)
{
    memset(dp, -1, sizeof dp);
  
    // Sort the given array
    sort(a, a + n);
  
    // Check it is possible rooted at i
    for (int i = 0; i < n; i++)
  
        // Check at both sides
        if (possibleWithState(0, i - 1, 1, a)
            && possibleWithState(i + 1, n - 1, 0, a)) {
            return true;
        }
  
    return false;
}
  
// Driver code
int main()
{
    int a[] = { 3, 6, 9, 18, 36, 108 };
    int n = sizeof(a) / sizeof(a[0]);
  
    if (isPossible(a, n))
        cout << "Yes";
    else
        cout << "No";
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
import java.util.*;
class GFG
{
      
static int __gcd(int a, int b) 
      
    // Everything divides 0 
    if (a == 0
        return b; 
    if (b == 0
        return a; 
      
    // base case 
    if (a == b) 
        return a; 
      
    // a is greater 
    if (a > b) 
        return __gcd(a - b, b); 
    return __gcd(a, b-a); 
  
// Maxium number of vertices
static final int N = 705;
  
// To store is it possible at
// particular pace or not
static int dp[][][] = new int[N][N][2];
  
// Return 1 if from l to r, it is 
// possible with the given state
static int possibleWithState(int l, int r,
                        int state, int a[])
{
    // Base condition
    if (l > r)
        return 1;
  
    // If it is already calculated
    if (dp[l][r][state] != -1)
        return dp[l][r][state];
  
    // Choose the root
    int root;
    if (state == 1)
        root = a[r + 1];
    else
        root = a[l - 1];
  
    // Traverse in range l to r
    for (int i = l; i <= r; i++) 
    {
  
        // If gcd is greater than one
        // check for both sides
        if (__gcd(a[i], root) > 1
        {
            int x = possibleWithState(l, i - 1, 1, a);
            if (x != 1)
                continue;
                  
            int y = possibleWithState(i + 1, r, 0, a);
              
            if (x == 1 && y == 1)
                return dp[l][r][state] = 1;
        }
    }
  
    // If not possible
    return dp[l][r][state] = 0;
}
  
// Function that return true if it is possible
// to make Binary Search Tree
static boolean isPossible(int a[], int n)
{
    for(int i = 0; i < dp.length; i++)
        for(int j = 0; j < dp[i].length; j++)
            for(int k = 0; k < dp[i][j].length; k++)
                dp[i][j][k]=-1;
  
    // Sort the given array
    Arrays.sort(a);
  
    // Check it is possible rooted at i
    for (int i = 0; i < n; i++)
  
        // Check at both sides
        if (possibleWithState(0, i - 1, 1, a) != 0 && 
            possibleWithState(i + 1, n - 1, 0, a) != 0)
        {
            return true;
        }
  
    return false;
}
  
// Driver code
public static void main(String args[])
{
    int a[] = { 3, 6, 9, 18, 36, 108 };
    int n = a.length;
  
    if (isPossible(a, n))
        System.out.println("Yes");
    else
        System.out.println("No");
  
}
}
  
// This code is contributed by 
// Arnab Kundu

chevron_right


Python3

# Python3 implementation of the appraoch
import math

# Maxium number of vertices
N = 705

# To store is it possible at
# particular pace or not
dp = [[[-1 for z in range(2)]
for x in range(N)]
for y in range(N)]

# Return 1 if from l to r, it is
# possible with the given state
def possibleWithState(l, r, state, a):

# Base condition
if (l > r):
return 1

# If it is already calculated
if (dp[l][r][state] != -1):
return dp[l][r][state]

# Choose the root
root = 0
if (state == 1) :
root = a[r + 1]
else:
root = a[l – 1]

# Traverse in range l to r
for i in range(l, r + 1):

# If gcd is greater than one
# check for both sides
if (math.gcd(a[i], root) > 1):
x = possibleWithState(l, i – 1, 1, a)
if (x != 1):
continue
y = possibleWithState(i + 1, r, 0, a)
if (x == 1 and y == 1) :
return 1

# If not possible
return 0

# Function that return true if it is
# possible to make Binary Search Tree
def isPossible(a, n):

# Sort the given array
a.sort()

# Check it is possible rooted at i
for i in range(n):

# Check at both sides
if (possibleWithState(0, i – 1, 1, a) and
possibleWithState(i + 1, n – 1, 0, a)):
return True

return False

# Driver Code
if __name__ == ‘__main__’:
a = [3, 6, 9, 18, 36, 108]
n = len(a)
if (isPossible(a, n)):
print(“Yes”)
else:
print(“No”)

# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)

C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the appraoch 
using System; 
  
class GFG 
      
static int __gcd(int a, int b) 
      
    // Everything divides 0 
    if (a == 0) 
        return b; 
    if (b == 0) 
        return a; 
      
    // base case 
    if (a == b) 
        return a; 
      
    // a is greater 
    if (a > b) 
        return __gcd(a - b, b); 
    return __gcd(a, b-a); 
  
// Maxium number of vertices 
static int N = 705; 
  
// To store is it possible at 
// particular pace or not 
static int [,,]dp = new int[N, N, 2]; 
  
// Return 1 if from l to r, it is 
// possible with the given state 
static int possibleWithState(int l, int r, 
                        int state, int []a) 
    // Base condition 
    if (l > r) 
        return 1; 
  
    // If it is already calculated 
    if (dp[l, r, state] != -1) 
        return dp[l, r, state]; 
  
    // Choose the root 
    int root; 
    if (state == 1) 
        root = a[r + 1]; 
    else
        root = a[l - 1]; 
  
    // Traverse in range l to r 
    for (int i = l; i <= r; i++) 
    
  
        // If gcd is greater than one 
        // check for both sides 
        if (__gcd(a[i], root) > 1) 
        
            int x = possibleWithState(l, i - 1, 1, a); 
            if (x != 1) 
                continue
                  
            int y = possibleWithState(i + 1, r, 0, a); 
              
            if (x == 1 && y == 1) 
                return dp[l,r,state] = 1; 
        
    
  
    // If not possible 
    return dp[l,r,state] = 0; 
  
// Function that return true 
// if it is possible to make 
// Binary Search Tree 
static bool isPossible(int []a, int n) 
    for(int i = 0; i < dp.GetLength(0); i++) 
        for(int j = 0; j < dp.GetLength(1); j++) 
            for(int k = 0; k < dp.GetLength(2); k++) 
                dp[i, j, k]=-1; 
  
    // Sort the given array 
    Array.Sort(a); 
  
    // Check it is possible rooted at i 
    for (int i = 0; i < n; i++) 
  
        // Check at both sides 
        if (possibleWithState(0, i - 1, 1, a) != 0 && 
            possibleWithState(i + 1, n - 1, 0, a) != 0) 
        
            return true
        
  
    return false
  
// Driver code 
public static void Main(String []args) 
    int []a = { 3, 6, 9, 18, 36, 108 }; 
    int n = a.Length; 
  
    if (isPossible(a, n)) 
        Console.WriteLine("Yes"); 
    else
        Console.WriteLine("No"); 
  
  
// This code is contributed by 29AjayKumar

chevron_right


Output:

Yes


My Personal Notes arrow_drop_up

pawanasipugmailcom

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.