Open In App

Split squares of first N natural numbers into two sets with minimum absolute difference of their sums

Last Updated : 01 Jun, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer N, the task is to partition the squares of first N( always a multiple of 8 ) natural numbers into two sets such that the difference of their subset sums is minimized. Print both the subsets as the required answer.

Examples:

Input: N = 8
Output:
0
1 16 36 49
4 9 25 64
Explanation: Squares of first N natural numbers are {1, 4, 9, 16, 25, 36, 49, 64}
Subsets {1, 16, 36, 49} and {4, 9, 25, 64} have sum 102. Therefore, difference of their sums is 0.

Input: N = 16
Output:
0
1 16 36 49 81 144 196 225
4 9 25 64 100 121 169 256

Naive Approach: The idea is to generate all possible pair of subsets splitting squares of first N natural numbers in between them and calculate subsets whose difference of the subset sums. Print the pair of subsets for which the difference of their sum is found to be minimum. 

Time Complexity: O(N*2N)
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach, the idea is to use the mathematical properties of the sum of continuous square numbers. Observe that, it is always possible to divide 8 contiguous square numbers into 2 sets such that their subset-sum difference is 0.

Proof:
8 contiguous square numbers can be divided into 2 subsets having difference of their sum as 0.
4 contiguous square numbers can be represented as k2, (k + 1)2, (k + 2)2 and (k + 3)2.

Let’s take 1st and 4th element in subset A. Therefore, 
Sum of A = k2 + (k+3)2
                    = 2k2 + 6k + 9

Let’s take 2nd and 3rd element in subset B. Therefore, 
Sum of B = (k + 1)2 + (k + 2)2
                    = 2k2 + 6k + 5
Subset difference = Sum of A – Sum of B = 4

Hence, 4 contiguous square numbers can be divided into 2 subsets having difference of their sum as 4.

Now, Lets say, the array of contiguous square is arr[] = {a1, a2, a3, a4, a5, a6, a7, a8}.
From the above property, it can be written that:
a1 + a4 – (a2 + a3) = 4 and 
a5 + a8 – (a6 + a7) = 4

Subtracting the above equations:
a1 + a4 – (a2 + a3) – (a5 + a8 – (a6 + a7)) = 0
Therefore, (a1 + a4 + a6 + a7) – (a2 + a3 + a5 + a8) = 0
Hence, 8 contiguous square numbers can be divided into 2 subsets having difference as 0.

 Follow the steps below to solve the problem:

  • Initialize a variable to store minimum subset difference and declare it to 0.
  • Initialize variable cnt to store the number of blocks of size 8 and divide N by 8 and store it in the variable cnt.
  • Initialize a string partition and store the partition pattern of N elements by concatenating string “ABBABAAB”, cnt number of times where “ABBABAAB” represents the subset that each element in a subarray of size 8 has to go in.
  • Initialize 2 vectors A and B to store elements of subset A and subset B.
  • Iterate a loop over the range [0, N – 1] and insert (i + 1)2 in vector A if pattern[i] is ‘A’. Otherwise, insert (i + 1)2 in vector B.
  • After the above steps, print the minimum subset difference, vector A and vector B.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to partition squares of N
// natural number in two subset
void minimumSubsetDifference(int N)
{
    // Store the count of blocks of size 8
    int blockOfSize8 = N / 8;
 
    // Partition of block of 8 element
    string str = "ABBABAAB";
 
    // Store the minimum subset difference
    int subsetDifference = 0;
 
    // Partition of N elements to minimize
    // their subset sum difference
    string partition = "";
    while (blockOfSize8--) {
        partition += str;
    }
 
    // Store elements of subset A and B
    vector<int> A, B;
 
    for (int i = 0; i < N; i++) {
 
        // If element is of type A
        if (partition[i] == 'A') {
            A.push_back((i + 1) * (i + 1));
        }
 
        // If the element is of type B
        else {
            B.push_back((i + 1) * (i + 1));
        }
    }
 
    // Print the minimum subset difference
    cout << subsetDifference << "\n";
 
    // Print the first subset
    for (int i = 0; i < A.size(); i++)
        cout << A[i] << " ";
 
    cout << "\n";
 
    // Print the second subset
    for (int i = 0; i < B.size(); i++)
        cout << B[i] << " ";
}
 
// Driver Code
int main()
{
    int N = 8;
 
    // Function Call
    minimumSubsetDifference(N);
 
    return 0;
}


Java




// Java program for the above approach
import java.util.Arrays;
 
class GFG{
 
// Function to partition squares of N
// natural number in two subset
static void minimumSubsetDifference(int N)
{
     
    // Store the count of blocks of size 8
    int blockOfSize8 = N / 8;
 
    // Partition of block of 8 element
    String str = "ABBABAAB";
 
    // Store the minimum subset difference
    int subsetDifference = 0;
 
    // Partition of N elements to minimize
    // their subset sum difference
    String partition = "";
    while (blockOfSize8-- > 0)
    {
        partition += str;
    }
 
    // Store elements of subset A and B
    int A[] = new int[N];
    int B[] = new int[N];
    int x = 0, y = 0;
 
    for(int i = 0; i < N; i++)
    {
         
        // If element is of type A
        if (partition.charAt(i) == 'A')
        {
            A[x++] = ((i + 1) * (i + 1));
        }
 
        // If the element is of type B
        else
        {
            B[y++] = ((i + 1) * (i + 1));
        }
    }
 
    // Print the minimum subset difference
    System.out.println(subsetDifference);
 
    // Print the first subset
    for(int i = 0; i < x; i++)
        System.out.print(A[i] + " ");
         
    System.out.println();
 
    // Print the second subset
    for(int i = 0; i < y; i++)
        System.out.print(B[i] + " ");
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 8;
     
    // Function Call
    minimumSubsetDifference(N);
}
}
 
// This code is contributed by shailjapriya


Python3




# Python3 program for the above approach
 
# Function to partition squares of N
# natural number in two subset
def minimumSubsetDifference(N):
     
    # Store the count of blocks of size 8
    blockOfSize8 = N // 8
 
    # Partition of block of 8 element
    str = "ABBABAAB"
 
    # Store the minimum subset difference
    subsetDifference = 0
     
    # Partition of N elements to minimize
    # their subset sum difference
    partition = ""
     
    while blockOfSize8 != 0:
        partition = partition + str
        blockOfSize8 = blockOfSize8 - 1
         
    # Store elements of subset A and B
    A = []
    B = []
     
    for i in range(N):
 
        # If element is of type A
        if partition[i] == 'A':
            A.append((i + 1) * (i + 1))
             
        # If the element is of type B
        else:
            B.append((i + 1) * (i + 1))
             
    # Print the minimum subset difference
    print(subsetDifference)
 
    # Print the first subset
    for i in A:
        print(i, end = " ")
    print()
     
    # Print the second subset
    for i in B:
        print(i, end = " ")
 
# Driver Code
N = 8
 
# Function call
minimumSubsetDifference(N)
 
# This code is contributed by shailjapriya


C#




// C# program for the above approach
using System;
 
class GFG{
 
    // Function to partition squares of N
    // natural number in two subset
    static void minimumSubsetDifference(int N)
    {
         
        // Store the count of blocks of size 8
        int blockOfSize8 = N / 8;
     
        // Partition of block of 8 element
        string str = "ABBABAAB";
     
        // Store the minimum subset difference
        int subsetDifference = 0;
     
        // Partition of N elements to minimize
        // their subset sum difference
        string partition = "";
        while (blockOfSize8-- > 0)
        {
            partition += str;
        }
     
        // Store elements of subset A and B
        int []A = new int[N];
        int []B = new int[N];
        int x = 0, y = 0;
     
        for(int i = 0; i < N; i++)
        {
             
            // If element is of type A
            if (partition[i] == 'A')
            {
                A[x++] = ((i + 1) * (i + 1));
            }
     
            // If the element is of type B
            else
            {
                B[y++] = ((i + 1) * (i + 1));
            }
        }
     
        // Print the minimum subset difference
        Console.WriteLine(subsetDifference);
     
        // Print the first subset
        for(int i = 0; i < x; i++)
            Console.Write(A[i] + " ");
             
        Console.WriteLine();
     
        // Print the second subset
        for(int i = 0; i < y; i++)
            Console.Write(B[i] + " ");
    }
     
    // Driver Code
    public static void Main(string[] args)
    {
        int N = 8;
         
        // Function Call
        minimumSubsetDifference(N);
    }
}
 
// This code is contributed by AnkitRai01


Javascript




<script>
// javascript program to implement
// the above approach
 
// Function to partition squares of N
// natural number in two subset
function minimumSubsetDifference(N)
{
      
    // Store the count of blocks of size 8
    let blockOfSize8 = N / 8;
  
    // Partition of block of 8 element
    let str = "ABBABAAB";
  
    // Store the minimum subset difference
    let subsetDifference = 0;
  
    // Partition of N elements to minimize
    // their subset sum difference
    let partition = "";
    while (blockOfSize8-- > 0)
    {
        partition += str;
    }
  
    // Store elements of subset A and B
    let A = [];
    let B = [];
    let x = 0, y = 0;
  
    for(let i = 0; i < N; i++)
    {
          
        // If element is of type A
        if (partition[i] == 'A')
        {
            A[x++] = ((i + 1) * (i + 1));
        }
  
        // If the element is of type B
        else
        {
            B[y++] = ((i + 1) * (i + 1));
        }
    }
  
    // Print the minimum subset difference
    document.write(subsetDifference + "<br/>");
  
    // Print the first subset
    for(let i = 0; i < x; i++)
        document.write(A[i] + " ");
          
    document.write("<br/>");
  
    // Print the second subset
    for(let i = 0; i < y; i++)
        document.write(B[i] + " ");
}
 
// Driver code
    let N = 8;
      
    // Function Call
    minimumSubsetDifference(N);
    
   // This code is contributed by splevel62.
</script>


Output

0
1 16 36 49 
4 9 25 64

Time Complexity: O(N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads