📌  相关文章
📜  将数字从1拆分为N,分为两个相等的总和子集

📅  最后修改于: 2021-05-08 18:30:24             🧑  作者: Mango

给定整数N ,任务是将1N的数字分为两个非空子集,以使集合中的元素之和相等。打印子集中的元素。如果我们不能形成任何子集,则打印-1

例子:

方法:为解决上述问题,我们必须观察整数N的三种情况以下是观察结果:

  1. 前N个自然数的总和是奇数:解决方案是不可能的,答案将是-1。因为我们不能将奇数和分成2个相等的一半。
  2. 当N为偶数时:在这种情况下,我们可以选择成对的数字并交替分配给每个集合。
    例如,N = 8,因此数为1,2,3,4,5,6,7,8,1,3,6,8可以在一组组合在一起。
    这是因为我们可以一次取1和N之间的两个数字并将它们分配给相同的集合,现在如果首先取1和N并将其分配给第一集合,那么如果我们将第一个数字即1加1并减少第二个数字,即N减一,总和保持不变(1 + N = 2 + N – 1) ,我们将2和N-1分配给第二个集合,因此按此顺序,我们可以将数字分成几对来代替每套。这里N = 2是一个例外
  3. 当N为奇数时:在这种情况下,每个子集的和为前N个自然数之和的一半。如果数字小于或等于所需的总和,则从N迭代到1 ,然后包含此数字;否则,如果数字大于所需的总和,则忽略该数字,并包含等于所需的数字和。另外,请跟踪用于一组的数字,以便我们可以找到另一子集的数字。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to print the two set
void findAns(int N)
{
    // Base case
    if (N <= 2) {
        cout << "-1";
        return;
    }
 
    // Sum of first numbers upto N
    int value = (N * (N + 1)) / 2;
     
    // Answer don't exist
    if(value&1)
    {
      cout<<"-1";
      return;
    }
 
    // To store the first set
    vector v1;
 
    // To store the second set
    vector v2;
 
    // When N is even
    if (!(N & 1)) {
 
        int turn = 1;
        int start = 1;
        int last = N;
        while (start < last) {
 
            if (turn) {
                v1.push_back(start);
                v1.push_back(last);
                turn = 0;
            }
            else {
                v2.push_back(start);
                v2.push_back(last);
                turn = 1;
            }
 
            // Increment start
            start++;
 
            // Decrement last
            last--;
        }
    }
 
    // When N is odd
    else {
 
        // Required sum of the subset
        int rem = value / 2;
 
        // Boolean array to keep
        // track of used elements
        bool vis[N + 1];
 
        for (int i = 1; i <= N; i++)
            vis[i] = false;
 
        vis[0] = true;
 
        // Iterate from N to 1
        for (int i = N; i >= 1; i--) {
            if (rem > i) {
                v1.push_back(i);
                vis[i] = true;
                rem -= i;
            }
 
            else {
                v1.push_back(rem);
                vis[rem] = true;
                break;
            }
        }
 
        // Assigning the unused
        // elements to second subset
        for (int i = 1; i <= N; i++) {
            if (!vis[i])
                v2.push_back(i);
        }
    }
 
    // Print the elements of first set
    cout << "Size of subset 1 is: ";
    cout << v1.size() << "\n";
    cout << "Elements of the subset are: ";
    for (auto c : v1)
        cout << c << " ";
 
    cout << endl;
 
    // Print the elements of second set
    cout << "Size of subset 2 is: ";
    cout << v2.size() << "\n";
    cout << "Elements of the subset are: ";
    for (auto c : v2)
        cout << c << " ";
}
 
// Driver Code
int main()
{
    // Given Number
    int N = 8;
 
    // Function Call
    findAns(N);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
  
class GFG{
     
// Function to print the two set
public static void findAns(int N)
{
    // Base case
    if (N <= 2)
    {
        System.out.print("-1");
        return;
    }
 
    // Sum of first numbers upto N
    int value = (N * (N + 1)) / 2;
       
    // Answer don't exist
      if(value&1)
    {
      System.out.print("-1");
      return;
    }
 
    // To store the first set
    Vector v1 = new Vector();
 
    // To store the second set
    Vector v2 = new Vector();
 
    // When N is even
    if ((N & 1) == 0)
    {
        int turn = 1;
        int start = 1;
        int last = N;
        while (start < last)
        {
            if (turn == 1)
            {
                v1.add(start);
                v1.add(last);
                turn = 0;
            }
            else
            {
                v2.add(start);
                v2.add(last);
                turn = 1;
            }
 
            // Increment start
            start++;
 
            // Decrement last
            last--;
        }
    }
 
    // When N is odd
    else
    {
         
        // Required sum of the subset
        int rem = value / 2;
 
        // Boolean array to keep
        // track of used elements
        boolean[] vis = new boolean[N + 1];
 
        for(int i = 1; i <= N; i++)
            vis[i] = false;
 
        vis[0] = true;
 
        // Iterate from N to 1
        for(int i = N; i >= 1; i--)
        {
            if (rem > i)
            {
                v1.add(i);
                vis[i] = true;
                rem -= i;
            }
            else
            {
                v1.add(rem);
                vis[rem] = true;
                break;
            }
        }
 
        // Assigning the unused
        // elements to second subset
        for(int i = 1; i <= N; i++)
        {
            if (!vis[i])
                v2.add(i);
        }
    }
 
    // Print the elements of first set
    System.out.print("Size of subset 1 is: ");
    System.out.println(v1.size());
    System.out.print("Elements of the subset are: ");
     
    for(Integer c : v1)    
        System.out.print(c + " ");
         
    System.out.println();
 
    // Print the elements of second set
    System.out.print("Size of subset 2 is: ");
    System.out.println(v2.size());
    System.out.print("Elements of the subset are: ");
     
    for(Integer c : v2)    
        System.out.print(c + " ");
}
 
// Driver code
public static void main(String[] args)
{
     
    // Given Number
    int N = 8;
 
    // Function Call
    findAns(N);
}
}
 
// This code is contributed by divyeshrabadiya07


Python3
# Python3 program for the
# above approach
 
# Function to print
# the two set
def findAns(N):
 
    # Base case
    if (N <= 2):
        print ("-1")
        return
    
    # Sum of first numbers upto N
    value = (N * (N + 1)) // 2
 
    # Answer don't exist
    if(value & 1):
        print ("-1")
        return
   
    # To store the first set
    v1 = []
 
    # To store the second set
    v2 = []
 
    # When N is even
    if (not (N & 1)):
        turn = 1
        start = 1
        last = N
         
        while (start < last):
            if (turn):
                v1.append(start)
                v1.append(last)
                turn = 0           
            else:
                v2.append(start)
                v2.append(last)
                turn = 1
 
            # Increment start
            start += 1
 
            # Decrement last
            last -= 1
     
    # When N is odd
    else:
 
        # Required sum of
        # the subset
        rem = value // 2
 
        # Boolean array to keep
        # track of used elements
        vis = [False] * (N + 1)
 
        for i in range (1, N + 1):
            vis[i] = False
 
        vis[0] = True
 
        # Iterate from N to 1
        for i in range (N , 0, -1):
            if (rem > i):
                v1.append(i)
                vis[i] = True
                rem -= i           
            else:
                v1.append(rem)
                vis[rem] = True
                break
            
        # Assigning the unused
        # elements to second subset
        for i in range (1, N + 1):
            if (not vis[i]):
               v2.append(i)
 
    # Print the elements of
    # first set
    print ("Size of subset 1 is: ",
           end = "")
    print (len( v1))
    print ("Elements of the subset are: ",
           end = "")
     
    for c in v1:
      print (c, end = " ")
 
    print ()
 
    # Print the elements of
    # second set
    print ("Size of subset 2 is: ",
           end = "")
    print(len( v2))
    print ("Elements of the subset are: ",
           end = "")
     
    for c in v2:
       print (c, end = " ")
 
# Driver Code
if __name__ == "__main__":
   
    # Given Number
    N = 8
 
    # Function Call
    findAns(N)
 
# This code is contributed by Chitranayal


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to print the two set
public static void findAns(int N)
{
     
    // Base case
    if (N <= 2)
    {
        Console.Write("-1");
        return;
    }
 
    // Sum of first numbers upto N
    int value = (N * (N + 1)) / 2;
   
    // Answer don't exist
    if(value&1)
    {
      Console.Write("-1");
      return;
    }
 
    // To store the first set
    List v1 = new List();
 
    // To store the second set
    List v2 = new List();
 
    // When N is even
    if ((N & 1) == 0)
    {
        int turn = 1;
        int start = 1;
        int last = N;
         
        while (start < last)
        {
            if (turn == 1)
            {
                v1.Add(start);
                v1.Add(last);
                turn = 0;
            }
            else
            {
                v2.Add(start);
                v2.Add(last);
                turn = 1;
            }
 
            // Increment start
            start++;
 
            // Decrement last
            last--;
        }
    }
 
    // When N is odd
    else
    {
         
        // Required sum of the subset
        int rem = value / 2;
 
        // Boolean array to keep
        // track of used elements
        bool[] vis = new bool[N + 1];
 
        for(int i = 1; i <= N; i++)
            vis[i] = false;
 
        vis[0] = true;
 
        // Iterate from N to 1
        for(int i = N; i >= 1; i--)
        {
            if (rem > i)
            {
                v1.Add(i);
                vis[i] = true;
                rem -= i;
            }
            else
            {
                v1.Add(rem);
                vis[rem] = true;
                break;
            }
        }
 
        // Assigning the unused
        // elements to second subset
        for(int i = 1; i <= N; i++)
        {
            if (!vis[i])
                v2.Add(i);
        }
    }
 
    // Print the elements of first set
    Console.Write("Size of subset 1 is: ");
    Console.WriteLine(v1.Count);
    Console.Write("Elements of the subset are: ");
     
    foreach(int c in v1)    
        Console.Write(c + " ");
         
    Console.WriteLine();
 
    // Print the elements of second set
    Console.Write("Size of subset 2 is: ");
    Console.WriteLine(v2.Count);
    Console.Write("Elements of the subset are: ");
     
    foreach(int c in v2)    
        Console.Write(c + " ");
}
 
// Driver code
public static void Main(String[] args)
{
     
    // Given number
    int N = 8;
 
    // Function call
    findAns(N);
}
}
 
// This code is contributed by Amit Katiyar


输出:
Size of subset 1 is: 4
Elements of the subset are: 1 8 3 6 
Size of subset 2 is: 4
Elements of the subset are: 2 7 4 5





时间复杂度: O(N)
辅助空间: O(N)