对于每个字符,可以通过将该字符与第一个字符交换并通过排除第一个字符来递归来生成排列(不包括重复约束)。
现在,如果我们想排除重复项,我们只需要确保我们不会将相同的字符放在第一个位置两次。可以通过对字符进行排序(因此重复的字符彼此相邻)并跳过与之前的字符相同或与目标位置的字符相同的任何字符来完成此操作。
Java 代码:(源自基本排列生成器)
import java.util.Arrays;
import java.util.Scanner;
public class NewMain
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter the string:");
String s = sc.nextLine();
char[] c = s.toCharArray();
Arrays.sort(c);
System.out.println("Here are all the permutations:");
NewMain.c = c;
count = 0;
permutation(0);
System.out.println("Number of permutations = " + count);
}
static char[] c;
static int count;
static void swap(int pos1, int pos2)
{
char temp = c[pos1];
c[pos1] = c[pos2];
c[pos2] = temp;
}
public static void permutation(int start)
{
if (start == c.length)
{
System.out.println(c);
count++;
}
for (int i = start; i < c.length; i++)
{
if (i == start || (c[i] != c[i-1] && c[i] != c[start]))
{
swap(start, i);
permutation(start + 1);
swap(start, i);
}
}
}
}
测试。
现在,如果重复字符太多,这仍然不是特别有效。我能想到的一种改进方法是对每个字符进行计数(可能以链表(计数的链表)的形式,这样我们就可以快速删除已达到 0 的计数,并插入它们之后返回)并且与上面类似,我们从左到右生成字符,通过在每个递归步骤中仅处理每个计数一次来跳过重复项。