给定整数N ,任务是将1到N的数字分为两个非空子集,以使集合中的元素之和相等。打印子集中的元素。如果我们不能形成任何子集,则打印-1 。
例子:
Input N = 4
Output:
Size of subset 1 is: 2
Elements of the subset are: 1 4
Size of subset 2 is: 2
Elements of the subset are: 2 3
Explanation:
The first and the second set have equal sum that is 5.
Input: N = 8
Output:
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
Explanation:
The first and the second set have equal sum that is 18.
方法:为解决上述问题,我们必须观察整数N的三种情况。以下是观察结果:
- 前N个自然数的总和是奇数:解决方案是不可能的,答案将是-1。因为我们不能将奇数和分成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是一个例外。 - 当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)