Related Articles

Related Articles

Split squares of first N natural numbers into two sets with minimum absolute difference of their sums
  • Last Updated : 07 Dec, 2020

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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Output

0
1 16 36 49 
4 9 25 64

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up
Recommended Articles
Page :