Javatpoint Logo
Javatpoint Logo

Number of Squareful Arrays in Java

An array containing only positive numbers is provided as input. We have to find out the total number of Squareful permutations of the array. An array is known as Squareful if the sum of each pair of adjacent elements is a perfect square.

Example 1:

Input

int inArr[] = {1, 3, 6}

Output

2

Explanation:

There are 6 permutations possible for the given array. {1, 3, 6}, {1, 6, 3}, {3, 1, 6}, {3, 6, 1}, {6, 1, 3}, {6, 3, 1}. In all of these 6 permutations, only {1, 3, 6}, and {6, 3, 1} form the Squareful arrays. For {1, 3, 6} we have 1 + 3 = 4 (22) and 3 + 6 = 9 (32), and for {6, 3, 1} we have 6 + 3 = 9 (32), and 1 + 3 = 4 (22).

Example 2:

Input

int inArr[] = {24, 48, 1}

Output

2

Explanation:

There are 6 permutations possible for the given array. {1, 24, 48}, {1, 48, 24}, {24, 1, 48}, {24, 48, 1}, {48, 1, 24}, {48, 24, 1}. In all of these 6 permutations, only {24, 1, 48}, and {48, 1, 24} form the Squareful arrays. For {24, 1, 48} we have 24 + 1 = 25 (52) and 1 + 48 = 49 (72), and for {48, 1, 24} we have 48 + 1 = 49 (72), and 1 + 24 = 25 (52).

Example 2:

Input

int inArr[] = {0, 0, 4, 0, 0}

Output

5

Explanation:

There are 5 permutations possible for the given array. {0, 0, 0, 0, 4}, {0, 0, 0, 4, 0}, {0, 0, 4, 0, 0}, {0, 4, 0, 0, 0}, {4, 0, 0, 0, 0}. All of these permutations are Squareful arrays. For {0, 0, 0, 0, 4}, we have 0 + 0 = 0 (02), 0 + 0 = 0 (02), 0 + 0 = 0 (02), 0 + 4 = 4 (22). Similar logic can be given for the other permutations too.

Simple Approach: Brute Force

In this approach, we check all of the permutations of the input array. And for every permutation in the input array 'inAr', check whether inAr[j] + inAr[j+1] is a perfect square or not. If it is a perfect square, then increase the ans by 1. Then return ans.

Algorithm:

  • Method for checking whether a specific permutation of 'inAr' is Squareful or not.
    • Make a method bool checkSquareful (int inAr[], int n)
    • Iterate 'j' from 0 to the length of 'inAr'.
      • If floor(sqrt(inAr[i] + inAr [i+1] )) != ceil(sqrt(inAr [i] + inAr[i+1])), return false.
    • Otherwise, return false.
  • Method for counting all of the Squareful permutations
    • Initialize an int 'cnt' = 0;
    • Sort the array 'inAr' in ascending order.
    • Run a do-while loop to check for all of the Squareful permutations.
    • do -> if checkSquareful (inAr) , then increase 'cnt'.
    • While keep checking for the next permutation of 'inAr'.

Now observe the following implementation.

Filename: SquarefulArrays.java

Output:

For the input array: 
0 0 0 0 4 
The number of Squareful array is: 5

For the input array: 
1 3 6 
The number of Squareful array is: 2

For the input array: 
24 48 1 
The number of Squareful array is: 2

Complexity Analysis: For the N size of the array, there are a total number of N! permutation. We are checking all of the permutations and each permutation is of the size N. Therefore, the overall time complexity of the program is O(N! * N). The space complexity of the program is O(1), as the program is not using any extra space.

The time complexity of the program is very high and is not suitable for larger inputs. Hence, some optimization is required. Observe the following approach.

Approach: Dynamic Programming Force

Make a graph where an edge exit from j to k if inAr[j] + inAr[k] is a perfect square. After that, count all of the possible Hamiltonian paths. Total number of Hamiltonian paths will be equal to the number of permutations that are Squareful.

Hamiltonian path is a graph path between two vertices of a graph such that all visit all the vertices of the graph at least once.

We will be constructing the graph where an edge between 'j' and 'k' is only if inAr[j] + inAr[k] is a perfect square. We can use dynamic programming techniques to check for the Hamiltonian paths.

Algorithm:

Step 1: We will first discard the repetitions and will only consider the index permutations. P[B, j] represents the total number of permutations when 'B' keeps the number we had already used, inAr[j] is the last number.

Step 2: 'B' is the binary number, where every bit represents where 'j' exits or not.

Step 3: In the beginning, P[1 << j, j] = 1. Other states are 0.

Step 4: Each time, enumerate 'k'.

  • If 'k' is not 'S', and inAr[j]+ inAr[k] is the perfect square, then,
    • P[B|1 << k, k] += P[B, j]

Step 5: Take a variable 'ans'. Assign value 0 to it.

Step 6: Iterate using 'j' from 0 to 's', where the size of the input array 'inAr' is 's'.

  • We get, 'ans' += P[(1 << s) - 1, j]

Step 7: It is required to count the repeated elements only once. Therefore divide 'ans' from the factorial of the count of every number in 'inAr[]'.

Filename: SquarefulArrays.java

Output:

For the input array: 
0 0 0 0 4 
The number of Squareful array is: 5

For the input array: 
1 3 6 
The number of Squareful array is: 2

For the input array: 
24 48 1 
The number of Squareful array is: 2

Complexity Analysis: There are a total of 'N x 2N' states, and for each state, there are up to 'N' children. Also, each child is traversed at least once. Therefore, the overall time complexity of the program is O(N2 x 2N). Also, the program uses a two-dimensional array 'P', which makes the space complexity of the program O(N x 2N), where N is the size of the input array.







Youtube For Videos Join Our Youtube Channel: Join Now

Feedback


Help Others, Please Share

facebook twitter pinterest

Learn Latest Tutorials


Preparation


Trending Technologies


B.Tech / MCA