没有重复的字符串的排列

时间:2015-01-29 02:28:57

标签: java algorithm

我阅读了生成字符串(solution)的所有排列问题的解决方案。

任何人都可以解释perm2与perm1的不同之处吗? (我觉得唯一的区别是perm1尝试将每个元素放在第一个位置,而perm2放在最后一个位置)

// print N! permutation of the characters of the string s (in order)
public  static void perm1(String s) { perm1("", s); }
private static void perm1(String prefix, String s) {
    int N = s.length();
    if (N == 0) System.out.println(prefix);
    else {
        for (int i = 0; i < N; i++)
           perm1(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, N));
    }

}

 // print N! permutation of the elements of array a (not in order)
    public static void perm2(String s) {
       int N = s.length();
       char[] a = new char[N];
       for (int i = 0; i < N; i++)
           a[i] = s.charAt(i);
       perm2(a, N);
    }

    private static void perm2(char[] a, int n) {
        if (n == 1) {
            System.out.println(a);
            return;
        }
        for (int i = 0; i < n; i++) {
            swap(a, i, n-1);
            perm2(a, n-1);
            swap(a, i, n-1);
        }
    }

另外,如果字符串中的某些字母相同,那么某些排列会相同吗?我能想到的唯一方法就是将结果保存在一个hashset中,以便只保留一个排列的实例。有更好的解决方案吗?

1 个答案:

答案 0 :(得分:1)

我希望第二种解决方案的理由是效率。它使用字符数组而不是String对象,并在每一步交换字符,而不是通过连接创建新的String。

就功能而言,两种解决方案之间的唯一区别是输出结果的顺序。

如果输入中有一些重复的字符,这是不正确的。如果需要,存储结果并检查唯一性(通过使用Set或直接通过contains)将是最简单的方法。

在第二种解决方案中,另一种方法是检查角色是否已被处理。这样可以避免存储结果集的开销(这对于长字符串来说可能很重要)。

在第二个perm2函数中:

if (n == 1) {
    System.out.println(a);
    return;
}
for (int i = n; i < a.length; i++) {
    if (a[i] == a[n-1])
        return;
}
for (int i = 0; i < n; i++) {
    boolean duplicate = false;
    for (int j = 0; !duplicate && j < i; j++)
        duplicate = a[i] == a[j];
    if (!duplicate) {
        swap(a, i, n-1);
        perm2(a, n-1);
        swap(a, i, n-1);
    }
}