Generate all unique partitions of an integer
Given a positive integer n, generate all possible unique ways to represent n as sum of positive integers.
Examples:
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
Solution: We print all partition in sorted order and numbers within a partition are also printed in sorted order (as shown in the above examples). The idea is to get the next partition using the values in the current partition. We store every partition in an array p[]. We initialize p[] as n where n is the input number. In every iteration. we first print p[] and then update p[] to store the next partition. So the main problem is to get the next partition from a given partition.
Steps to get next partition from current partition:
We are given current partition in p[] and its size. We need to update p[] to store next partition. Values in p[] must be sorted in non-increasing order.
- Find the rightmost non-one value in p[] and store the count of 1’s encountered before a non-one value in a variable rem_val (It indicates sum of values on right side to be updated). Let the index of non-one value be k.
- Decrease the value of p[k] by 1 and increase rem_val by 1. Now there may be two cases:
- a) If p[k] is more than or equal to rem_val. This is a simple case (we have the sorted order in new partition). Put rem_val at p[k+1] and p[0…k+1] is our new partition.
- b) Else (This is a interesting case, take initial p[] as {3, 1, 1, 1}, p[k] is decreased from 3 to 2, rem_val is increased from 3 to 4, divide rem_val in different values of size p[k] and copy these values at different positions after p[k], so the next partition should be {2, 2, 2}).
- Copy p[k] to next position, increment k and reduce count by p[k] while p[k] is less than rem_val. Finally, put rem_val at p[k+1] and p[0…k+1] is our new partition. This step is like dividing rem_val in terms of p[k] (4 is divided in 2’s).
Following is the implementation of above algorithm:
C++
// CPP program to generate all unique // partitions of an integer #include<iostream> 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
<?php // PHP program to generate // all unique partitions // of an integer // A utility function to // print an array p[] of // size 'n' function printArray( $p , $n ) { for ( $i = 0; $i < $n ; $i ++) echo $p [ $i ] , " " ; echo "\n" ; } function printAllUniqueParts( $n ) { // An array to store // a partition $p [ $n ] = array (0); // Index of last element // in a partition $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 $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 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
<script> // Javascript program to generate all unique // partitions of an integer // Function to print an array p[] // of size n function printArray(p, n) { for (let i = 0; i < n; i++) document.write(p[i] + " " ); document.write( "</br>" ); } // Function to generate all unique // partitions of an integer function printAllUniqueParts(n) { // An array to store a partition let p = new Array(n); // Index of last element in a // partition let 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 let 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 code document.write( "All Unique Partitions of 2" + "</br>" ); printAllUniqueParts(2); document.write( "All Unique Partitions of 3" + "</br>" ); printAllUniqueParts(3); document.write( "All Unique Partitions of 4" + "</br>" ); printAllUniqueParts(4); // This code is contributed by divyesh072019 </script> |
Output:
All Unique Partitions of 2 2 1 1 All Unique Partitions of 3 3 2 1 1 1 1 All Unique Partitions of 4 3 1 2 2 2 1 1 1 1 1 1
Time Complexity: O(n * k)
Auxiliary Space: O(n)
Recursive Approach:
The idea behind this approach is to find maximum sum by taking and not-taking concept, if we are taking an element it must by at least at a difference of two from the previous taken elements index.
Below are the steps :
- Take a vector and store elements from 1 to n
- create solve function to find set of elements having sum=n
- we have two base cases:
- if(sum==n) store the vector in a vector<vector<int>> and return
- if(index<0) return directly
- recursively traverse a vector by not taking any element initially
- above recursive function returns a call at index =0
- next we take element in a vector and then find recursively its 2nd neighbour
- then we pop element that was last pushed.
- final answer is returned.
Here is the complete implementation of the approach:
C++
// c++ code #include <bits/stdc++.h> using namespace std; class Solution { public : vector< int > temp; void solve(vector< int > a, vector<vector< int > >& v, int idx, int sum, int n) { // first base case if sum=n we can store vector in a // vector if (sum == n) { v.push_back(temp); return ; } // if idx < 0 return if (idx < 0) { return ; } // not take condition solve(a, v, idx - 1, sum, n); if (sum < n) { temp.push_back(a[idx]); // this is main condition where we can take one // element many times solve(a, v, idx, sum + a[idx], n); temp.pop_back(); } } vector<vector< int > > UniquePartitions( int n) { vector< int > a; // vector to store elements from 1 to n for ( int i = 1; i <= n; i++) { a.push_back(i); } vector<vector< int > > v; // call solve to get answer solve(a, v, n - 1, 0, n); reverse(v.begin(), v.end()); return v; } }; int main() { Solution ob; vector<vector< int > > ans = ob.UniquePartitions(4); cout << "for 4\n" ; for ( auto i : ans) { for ( auto j : i) { cout << j << " " ; } cout << "\n" ; } vector<vector< int > > a = ob.UniquePartitions(3); cout << "\n" ; cout << "for 3\n" ; for ( auto i : a) { for ( auto j : i) { cout << j << " " ; } cout << "\n" ; } return 0; } |
Java
// Java code for the above approach import java.util.ArrayList; class Solution { private ArrayList<Integer> temp = new ArrayList<Integer>(); public void solve( int [] a, ArrayList<ArrayList<Integer>> v, int idx, int s, int n) { // first base case if sum=n we can store ArrayList in v if (s == n) { v.add( new ArrayList<Integer>(temp)); return ; } // if idx < 0 return if (idx < 0 ) { return ; } // not take condition solve(a, v, idx- 1 , s, n); if (s < n) { temp.add(a[idx]); // this is main condition where we can take one // element many times solve(a, v, idx, s+a[idx], n); temp.remove(temp.size()- 1 ); } } public ArrayList<ArrayList<Integer>> uniquePartitions( int n) { int [] a = new int [n]; for ( int i = 0 ; i < n; i++) { a[i] = i+ 1 ; } ArrayList<ArrayList<Integer>> v = new ArrayList<ArrayList<Integer>>(); // call solve to get answer solve(a, v, n- 1 , 0 , n); // reverse the ArrayList for ( int i = 0 ; i < v.size() / 2 ; i++) { ArrayList<Integer> temp = v.get(i); v.set(i, v.get(v.size()-i- 1 )); v.set(v.size()-i- 1 , temp); } return v; } public static void main(String[] args) { Solution sol = new Solution(); ArrayList<ArrayList<Integer>> ans = sol.uniquePartitions( 4 ); System.out.println( "for 4" ); for (ArrayList<Integer> arr : ans) { System.out.println(arr); } ArrayList<ArrayList<Integer>> a = sol.uniquePartitions( 3 ); System.out.println( "\nfor 3" ); for (ArrayList<Integer> arr : a) { System.out.println(arr); } } } |
Python3
#Python code for the above approach class Solution: def __init__( self ): self .temp = [] def solve( self , a, v, idx, s, n): # first base case if sum=n we can store vector in a # vector if s = = n: v.append( self .temp.copy()) return # if idx < 0 return if idx < 0 : return # not take condition self .solve(a, v, idx - 1 , s, n) if s < n: self .temp.append(a[idx]) # this is main condition where we can take one # element many times self .solve(a, v, idx, s + a[idx], n) self .temp.pop() def UniquePartitions( self , n): a = [i for i in range ( 1 , n + 1 )] v = [] # call solve to get answer self .solve(a, v, n - 1 , 0 , n) v.reverse() return v sol = Solution() ans = sol.UniquePartitions( 4 ) print ( "for 4" ) for i in ans: print (i) a = sol.UniquePartitions( 3 ) print ( "\nfor 3" ) for i in a: print (i) |
C#
using System; using System.Collections.Generic; class Solution { List< int > temp = new List< int >(); public void solve(List< int > a, List<List< int >> v, int idx, int sum, int n) { // Base case: if the sum is equal to n, store the temp vector in the result vector. if (sum == n) { v.Add( new List< int >(temp)); return ; } // If idx is less than 0, return. if (idx < 0) { return ; } // Not taking condition. solve(a, v, idx - 1, sum, n); if (sum < n) { temp.Add(a[idx]); // This is the main condition where we can take one element multiple times. solve(a, v, idx, sum + a[idx], n); temp.RemoveAt(temp.Count - 1); } } public List<List< int >> UniquePartitions( int n) { List< int > a = new List< int >(); // Store elements from 1 to n in the a vector. for ( int i = 1; i <= n; i++) { a.Add(i); } List<List< int >> v = new List<List< int >>(); // Call solve to get the result. solve(a, v, n - 1, 0, n); v.Reverse(); return v; } } class Program { static void Main( string [] args) { Solution ob = new Solution(); List<List< int >> ans = ob.UniquePartitions(4); Console.WriteLine( "for 4" ); foreach ( var i in ans) { foreach ( var j in i) { Console.Write(j + " " ); } Console.WriteLine(); } List<List< int >> a = ob.UniquePartitions(3); Console.WriteLine(); Console.WriteLine( "for 3" ); foreach ( var i in a) { foreach ( var j in i) { Console.Write(j + " " ); } Console.WriteLine(); } } } |
Javascript
class Solution { constructor() { this .temp = []; } solve(a, v, idx, s, n) { // first base case if sum=n we can store vector in a vector if (s === n) { v.push([... this .temp]); return ; } // if idx < 0 return if (idx < 0) { return ; } // not take condition this .solve(a, v, idx - 1, s, n); if (s < n) { this .temp.push(a[idx]); // this is main condition where we can take one element many times this .solve(a, v, idx, s + a[idx], n); this .temp.pop(); } } uniquePartitions(n) { const a = Array.from({ length: n }, (_, i) => i + 1); const v = []; // call solve to get answer this .solve(a, v, n - 1, 0, n); v.reverse(); return v; } } const sol = new Solution(); let ans = sol.uniquePartitions(4); console.log( "for 4" ); ans.forEach(i => console.log(i)); ans = sol.uniquePartitions(3); console.log( "\nfor 3" ); ans.forEach(i => console.log(i)); |
for 4 4 3 1 2 2 2 1 1 1 1 1 1 for 3 3 2 1 1 1 1
Time Complexity: O(2^n)
Auxiliary Space: O(2^n)
This article is contributed by Hariprasad NG. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Please Login to comment...