📜  生成整数的所有唯一分区

📅  最后修改于: 2021-05-06 19:29:41             🧑  作者: Mango

给定一个正整数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 []中的值必须以非递增顺序排序。

  1. 在p []中找到最右边的非1值,并将遇到的1的计数存储在变量rem_val中的非1值之前(它表示要更新的右侧的值之和)。令非一个值的索引为k。
  2. 将p [k]的值减小1,并将rem_val增大1。现在可能有两种情况:
    • a)如果p [k]大于或等于rem_val。这是一个简单的案例(我们在新分区中具有排序顺序)。将rem_val放在p [k + 1],p [0…k + 1]是我们的新分区。
    • b)其他(这是一个有趣的情况,将初始p []设为{3,1,1,1},p [k]从3减少到2,rem_val从3增加到4,下一个分区应该是{2,2,2})。
  3. 将p [k]复制到下一个位置,将k递增,并在p [k]小于rem_val时将计数减少p [k]。最后,将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