给定一个正整数 n,生成所有可能的唯一方式来将 n 表示为正整数之和。
例子:
Input: n = 2
Output:
2
1 1
Input: n = 3
Output:
3
2 1
1 1 1
Note: 2+1 and 1+2 are considered as duplicates.
Input: n = 4
Output:
4
3 1
2 2
2 1 1
1 1 1 1
解决方案:我们按排序顺序打印所有分区,分区内的数字也按排序顺序打印(如上例所示)。这个想法是使用当前分区中的值来获取下一个分区。我们将每个分区存储在一个数组 p[] 中。我们将 p[] 初始化为 n,其中 n 是输入数字。在每次迭代中。我们首先打印 p[] 然后更新 p[] 来存储下一个分区。所以主要问题是从给定的分区中获取下一个分区。
从当前分区获取下一个分区的步骤:
我们给出了 p[] 中的当前分区及其大小。我们需要更新 p[] 来存储下一个分区。 p[] 中的值必须按非递增顺序排序。
- 在 p[] 中找到最右边的非 1 值并将在非 1 值之前遇到的 1 的计数存储在变量 rem_val 中(它表示要更新的右侧值的总和)。设非一值的索引为k。
- 将p[k]的值减1,rem_val加1,现在可能有两种情况:
- a) 如果p[k] 大于或等于 rem_val。这是一个简单的情况(我们在新分区中有排序顺序)。将 rem_val 放在 p[k+1] 处,p[0…k+1] 是我们的新分区。
- b) Else (这是一个有趣的例子,取初始 p[] 为 {3, 1, 1, 1},p[k] 从 3 减少到 2,rem_val 从 3 增加到 4,下一个分区应该是{2, 2, 2})。
- 将 p[k] 复制到下一个位置,增加 k 并将计数减少 p[k],而 p[k] 小于 rem_val。最后,将 rem_val 放在 p[k+1] 处,p[0…k+1] 是我们的新分区。这一步就像根据 p[k] 划分 rem_val(4 被划分为 2)。
以下是上述算法的实现:
C++
// CPP program to generate all unique
// partitions of an integer
#include
using namespace std;
// A utility function to print an array p[] of size 'n'
void printArray(int p[], int n)
{
for (int i = 0; i < n; i++)
cout << p[i] << " ";
cout << endl;
}
void printAllUniqueParts(int n)
{
int p[n]; // An array to store a partition
int k = 0; // Index of last element in a partition
p[k] = n; // Initialize first partition as number itself
// This loop first prints current partition then generates next
// partition. The loop stops when the current partition has all 1s
while (true)
{
// print current partition
printArray(p, k+1);
// Generate next partition
// Find the rightmost non-one value in p[]. Also, update the
// rem_val so that we know how much value can be accommodated
int rem_val = 0;
while (k >= 0 && p[k] == 1)
{
rem_val += p[k];
k--;
}
// if k < 0, all the values are 1 so there are no more partitions
if (k < 0) return;
// Decrease the p[k] found above and adjust the rem_val
p[k]--;
rem_val++;
// If rem_val is more, then the sorted order is violated. Divide
// rem_val in different values of size p[k] and copy these values at
// different positions after p[k]
while (rem_val > p[k])
{
p[k+1] = p[k];
rem_val = rem_val - p[k];
k++;
}
// Copy rem_val to next position and increment position
p[k+1] = rem_val;
k++;
}
}
// Driver program to test above functions
int main()
{
cout << "All Unique Partitions of 2 \n";
printAllUniqueParts(2);
cout << "\nAll Unique Partitions of 3 \n";
printAllUniqueParts(3);
cout << "\nAll Unique Partitions of 4 \n";
printAllUniqueParts(4);
return 0;
}
Java
// Java program to generate all unique
// partitions of an integer
import java.io.*;
class GFG
{
// Function to print an array p[] of size n
static void printArray(int p[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(p[i]+" ");
System.out.println();
}
// Function to generate all unique partitions of an integer
static void printAllUniqueParts(int n)
{
int[] p = new int[n]; // An array to store a partition
int k = 0; // Index of last element in a partition
p[k] = n; // Initialize first partition as number itself
// This loop first prints current partition then generates next
// partition. The loop stops when the current partition has all 1s
while (true)
{
// print current partition
printArray(p, k+1);
// Generate next partition
// Find the rightmost non-one value in p[]. Also, update the
// rem_val so that we know how much value can be accommodated
int rem_val = 0;
while (k >= 0 && p[k] == 1)
{
rem_val += p[k];
k--;
}
// if k < 0, all the values are 1 so there are no more partitions
if (k < 0) return;
// Decrease the p[k] found above and adjust the rem_val
p[k]--;
rem_val++;
// If rem_val is more, then the sorted order is violated. Divide
// rem_val in different values of size p[k] and copy these values at
// different positions after p[k]
while (rem_val > p[k])
{
p[k+1] = p[k];
rem_val = rem_val - p[k];
k++;
}
// Copy rem_val to next position and increment position
p[k+1] = rem_val;
k++;
}
}
// Driver program
public static void main (String[] args)
{
System.out.println("All Unique Partitions of 2");
printAllUniqueParts(2);
System.out.println("All Unique Partitions of 3");
printAllUniqueParts(3);
System.out.println("All Unique Partitions of 4");
printAllUniqueParts(4);
}
}
// Contributed by Pramod Kumar
Python3
# A utility function to print an
# array p[] of size 'n'
def printArray(p, n):
for i in range(0, n):
print(p[i], end = " ")
print()
def printAllUniqueParts(n):
p = [0] * n # An array to store a partition
k = 0 # Index of last element in a partition
p[k] = n # Initialize first partition
# as number itself
# This loop first prints current partition,
# then generates next partition.The loop
# stops when the current partition has all 1s
while True:
# print current partition
printArray(p, k + 1)
# Generate next partition
# Find the rightmost non-one value in p[].
# Also, update the rem_val so that we know
# how much value can be accommodated
rem_val = 0
while k >= 0 and p[k] == 1:
rem_val += p[k]
k -= 1
# if k < 0, all the values are 1 so
# there are no more partitions
if k < 0:
print()
return
# Decrease the p[k] found above
# and adjust the rem_val
p[k] -= 1
rem_val += 1
# If rem_val is more, then the sorted
# order is violated. Divide rem_val in
# different values of size p[k] and copy
# these values at different positions after p[k]
while rem_val > p[k]:
p[k + 1] = p[k]
rem_val = rem_val - p[k]
k += 1
# Copy rem_val to next position
# and increment position
p[k + 1] = rem_val
k += 1
# Driver Code
print('All Unique Partitions of 2')
printAllUniqueParts(2)
print('All Unique Partitions of 3')
printAllUniqueParts(3)
print('All Unique Partitions of 4')
printAllUniqueParts(4)
# This code is contributed
# by JoshuaWorthington
C#
// C# program to generate all unique
// partitions of an integer
using System;
class GFG {
// Function to print an array p[]
// of size n
static void printArray(int []p, int n)
{
for (int i = 0; i < n; i++)
Console.Write(p[i]+" ");
Console.WriteLine();
}
// Function to generate all unique
// partitions of an integer
static void printAllUniqueParts(int n)
{
// An array to store a partition
int[] p = new int[n];
// Index of last element in a
// partition
int k = 0;
// Initialize first partition as
// number itself
p[k] = n;
// This loop first prints current
// partition, then generates next
// partition. The loop stops when
// the current partition has all 1s
while (true)
{
// print current partition
printArray(p, k+1);
// Generate next partition
// Find the rightmost non-one
// value in p[]. Also, update
// the rem_val so that we know
// how much value can be
// accommodated
int rem_val = 0;
while (k >= 0 && p[k] == 1)
{
rem_val += p[k];
k--;
}
// if k < 0, all the values are 1 so
// there are no more partitions
if (k < 0)
return;
// Decrease the p[k] found above
// and adjust the rem_val
p[k]--;
rem_val++;
// If rem_val is more, then the sorted
// order is violated. Divide rem_val in
// different values of size p[k] and copy
// these values at different positions
// after p[k]
while (rem_val > p[k])
{
p[k+1] = p[k];
rem_val = rem_val - p[k];
k++;
}
// Copy rem_val to next position and
// increment position
p[k+1] = rem_val;
k++;
}
}
// Driver program
public static void Main ()
{
Console.WriteLine("All Unique Partitions of 2");
printAllUniqueParts(2);
Console.WriteLine("All Unique Partitions of 3");
printAllUniqueParts(3);
Console.WriteLine("All Unique Partitions of 4");
printAllUniqueParts(4);
}
}
// This code is contributed by Sam007.
PHP
= 0 && $p[$k] == 1)
{
$rem_val += $p[$k];
$k--;
}
// if k < 0, all the values
// are 1 so there are no
// more partitions
if ($k < 0) return;
// Decrease the p[k] found
// above and adjust the
// rem_val
$p[$k]--;
$rem_val++;
// If rem_val is more, then
// the sorted order is violated.
// Divide rem_val in different
// values of size p[k] and copy
// these values at different
// positions after p[k]
while ($rem_val > $p[$k])
{
$p[$k + 1] = $p[$k];
$rem_val = $rem_val - $p[$k];
$k++;
}
// Copy rem_val to next
// position and increment
// position
$p[$k + 1] = $rem_val;
$k++;
}
}
// Driver Code
echo "All Unique Partitions of 2 \n";
printAllUniqueParts(2);
echo "\nAll Unique Partitions of 3 \n";
printAllUniqueParts(3);
echo "\nAll Unique Partitions of 4 \n";
printAllUniqueParts(4);
// This code is contributed
// by akt_mit
?>
Javascript
输出:
All Unique Partitions of 2
2
1 1
All Unique Partitions of 3
3
2 1
1 1 1
All Unique Partitions of 4
4
3 1
2 2
2 1 1
1 1 1 1
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。