修改算法以在包含重复项的字符串中生成唯一排列

modifying algorithm to generate unique permutations in a string that contains duplicates

如果我要使用交换和置换方法来生成排列,我知道如何处理重复项问题 here

但是,我使用了一种不同的方法,我将当前字符放在任意两个字符之间,在开头和结尾,在没有当前角色。

我如何修改下面的代码,以便在包含重复项的字符串中仅提供唯一的排列

import java.util.ArrayList;

public class Permutations {
    public static void main(String[] args) {
        String str = "baab";
        System.out.println(fun(str, 0));
        System.out.println("number of Permutations =="+fun(str, 0).size());
    }

    static ArrayList<String> fun(String str, int index)
    {
        if(index == str.length())
        {
            ArrayList<String> al = new ArrayList<String>();
            al.add("");
            return al;
        }

        /* get return from lower frame */
        ArrayList<String> rec = fun(str, index+1);

        /* get character here */
        char c = str.charAt(index);

        /* to each of the returned Strings in ArrayList, add str.charAt(j) */
        ArrayList<String> ret = new ArrayList<String>();
        for(int i = 0;i<rec.size();i++)
        {
            String here = rec.get(i);
            ret.add(c + here);
            for(int j = 0;j<here.length();j++)
                ret.add(here.substring(0,j+1) + c + here.substring(j+1,here.length()));
        }
        return ret;
    }
}

此时,"bab"这样的字符串会产生如下输出,多次包含abb和bba。

[bab, abb, abb, bba, bba, bab]
number of Permutations ==6

PS : 我不想使用 hashmap/Set 来跟踪我的重复项并查看它们以前是否遇到过。

当您遍历字符串并在每个位置添加字符时,如果您在字符串中找到与您要插入的字符相同的字符,请在紧接其前插入新字符后中断。这意味着具有相同字符不止一次的字符串只能以一种方式形成(通过以相反的顺序插入),因此不会发生重复。

for(int j = 0;j<here.length();j++)
{
    if(here.charAt(j) == c)
        break;  
    ret.add(here.substring(0,j+1) + c + here.substring(j+1,here.length()));
}

解决这些涉及没有重复项的生成集的问题的一般方法是考虑一个 属性 每组重复项中只有一个,然后将其作为约束强制执行。例如,在这种情况下,约束是 "all duplicated characters are added in reverse order"(前向顺序同样有效,但您必须翻转循环方向)。对于顺序不重要的组合问题,约束可以是 "items in each list are in ascending order"。等等。