Open In App

Print all Unique permutations of a given string.

Last Updated : 24 Jan, 2025
Comments
Improve
Suggest changes
1 Like
Like
Report

Given a string that may contain duplicates, the task is find all unique permutations of given string in any order.

Examples: 

Input: “ABC”
Output: [“ABC”, “ACB”, “BAC”, “BCA”, “CAB”, “CBA”]
Explanation: Given string ABC has 6 unique permutations as “ABC”, “ACB”, “BAC”, “BCA”, “CAB” and “CBA”.

Input: “AAA”
Output: [“AAA”]
Explanation: No other unique permutations can be formed as all the characters are same.

[Naive Approach] Generating All Permutations

The idea is to generate all possible permutations of a given string and store them in a hash set. The generated permutations were stored in hash set, to ensures that only unique permutations are retained as hashset does not allow duplicates. Once all permutations have been generated, we transfer the permutations from hash set to the result array.

This method is particularly useful when dealing with input strings that contain duplicate characters. Instead of manually handling the duplicates during the permutation generation, the use of a unordered set simplifies the process by eliminating duplicates automatically.

CPP
// C++ program to print unique permutation of string  using hash set.

#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;

// Function genPermutation is used to generate all possible permutaion.
void genPermutation(int i, string &s, vector<bool> &used, 
                    string &curr, unordered_set<string>& st) {
    if (i == s.size()) {

        // Add the permutation to the result set
        st.insert(curr);
        return;
    }

    for (int j = 0; j < s.size(); j++) {
        if (!used[j]) {

            // Mark the character as used
            used[j] = true;
          	curr.push_back(s[j]);
			
            // Recurse with the next character
            genPermutation(i + 1, s, used, curr,st);
          	
            // Backtrack and unmark the character
          	used[j] = false;
          	curr.pop_back();
        }
    }
}

vector<string> findPermutation(string &s) {

    // To track if a character is used
    vector<bool> used(s.size(), false);
    unordered_set<string> st;
  
  	string curr = "";

    // Start the recursion
    genPermutation(0, s, used, curr, st);

    // Convert the set to a vector
    vector<string> res(st.begin(), st.end());
    return res;
}

int main() {
    string s = "ABC";
    vector<string> res = findPermutation(s);

    // Print the permutations
    for (string perm: res)
        cout << perm << " ";

    return 0;
}
Java Python C# JavaScript

Output
CBA BAC CAB BCA ABC ACB 

Time Complexity: O(n*n!), where n is the size of the array.
Auxiliary Space: O(n!), space used by hash set.

[Expected Approach] Generating Only Unique Permutations

This approach is similar to generating all possible permutation. Now in this approach, while generating the permutations, at each index during recursion, we only consider the unique available characters. To track the availability of characters we use hash map.

Duplicate permutations are generated in the previous approach because it treats identical characters, like the two ‘B’s in “ABBC,” as distinct due to their indices. For example, when placing a ‘B’ at an index, choosing the first or second ‘B’ results in the same permutation (e.g., “ABBC” or “ABBC” again), leading to duplicates.

In this approach, we prune branches in the recursive tree that would generate duplicate permutations and place only unique available characters at each index.

C++
//C++ program to print unique permutation of string 
//using hash map.
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;

// Recursive function to generate permutations
void genPermutations(int n, string &curr ,unordered_map<char, int> &cnt,
                     		vector<string>& res) {
    
    // Base case: If the current permutation length equals the input
    // string length, add it to the result
    if (curr.size() == n) {
        res.push_back(curr);
        return;
    }

    // Iterate through each character in the frequency map
    for (pair<char, int> it: cnt) {
        char c = it.first;
        int count = it.second;

        // Skip characters with a count of 0
        if (count == 0) 
            continue;

        // Include the character in the current permutation
        curr.push_back(c);

        // Decrease its count in the frequency map
        cnt[c]--;

        // Recur to build the next character in the permutation
        genPermutations(n, curr, cnt , res);

        // Backtrack: Remove the character and restore its count
        curr.pop_back();
        cnt[c]++;
    }
}

// Function to find all unique permutations of the input string
vector<string> findPermutation(string s) {
  
  // Vector to store the result
    vector<string> res; 
  
   // Frequency map to count occurrences of each character
    unordered_map<char, int> cnt;   

    // Populate the frequency map with the characters of the input string
    for (char c : s) 
        cnt[c]++;

    // To build permutations
    string curr = "";
    genPermutations(s.size(), curr, cnt, res);
    return res;
}

int main() {
    string s = "ABC";
    vector<string> res = findPermutation(s);

    for (string perm: res)
        cout << perm << " ";

    return 0;
}
Java Python C# JavaScript

Output
CBA CAB BCA BAC ACB ABC 

Time Complexity: O(n*n!), In worst case all characters were unique, so it take time equal to generating all permutations.
Auxiliary Space: O(n), used by temporary string and hash map.
 



Next Article

Similar Reads