Python 如何生成置换而不生成重复结果,但使用固定数量的字符

Python 如何生成置换而不生成重复结果,但使用固定数量的字符,python,algorithm,permutation,itertools,Python,Algorithm,Permutation,Itertools,我试图找出一种方法来生成一个字符串的所有可能排列,该字符串有两个重复字符,但不生成重复元组 现在我正在使用itertools.permutations()。它可以工作,但我需要删除重复,而我不能使用set()删除重复 我期待什么样的结果?例如,我想得到DDRR的所有组合,使用itertools.permutations()的问题是,我会得到DDRR大约四次,因为itertools看到Ds,就好像它们是不同的,与Rs一样 使用列表(itertools.permutations('DDRR'))我得

我试图找出一种方法来生成一个字符串的所有可能排列,该字符串有两个重复字符,但不生成重复元组

现在我正在使用
itertools.permutations()
。它可以工作,但我需要删除重复,而我不能使用
set()
删除重复

我期待什么样的结果?例如,我想得到
DDRR
的所有组合,使用
itertools.permutations()
的问题是,我会得到
DDRR
大约四次,因为
itertools
看到
D
s,就好像它们是不同的,与
R
s一样

使用
列表(itertools.permutations('DDRR'))
我得到:

[('D', 'D', 'R', 'R'), ('D', 'D', 'R', 'R'), ('D', 'R', 'D', 'R'), ('D', 'R', 'R', 'D'), ('D', 'R', 'D', 'R'), ('D', 'R', 'R', 'D'), ('D', 'D', 'R', 'R'), ('D', 'D', 'R', 'R'), ('D', 'R', 'D', 'R'), ('D', 'R', 'R', 'D'), ('D', 'R', 'D', 'R'), ('D', 'R', 'R', 'D'), ('R', 'D', 'D', 'R'), ('R', 'D', 'R', 'D'), ('R', 'D', 'D', 'R'), ('R', 'D', 'R', 'D'), ('R', 'R', 'D', 'D'), ('R', 'R', 'D', 'D'), ('R', 'D', 'D', 'R'), ('R', 'D', 'R', 'D'), ('R', 'D', 'D', 'R'), ('R', 'D', 'R', 'D'), ('R', 'R', 'D', 'D'), ('R', 'R', 'D', 'D')]
我想要的理想结果是:

[('D', 'R', 'R', 'D'), ('R', 'D', 'R', 'D'), ('R', 'R', 'D', 'D'), ('D', 'R', 'D', 'R'), ('D', 'D', 'R', 'R'), ('R', 'D', 'D', 'R')]

这将是创建具有重复元素的集合置换的标准方法:计算每个元素的发生次数(例如使用关联数组或字典),循环字典中的元素,每次将元素附加到置换,并与字典的其余部分一起递归。但是,对于很长的输入阵列,它永远不会很快;但那就没什么可能了

(JavaScript代码示例;我不会说Python;翻译应该足够简单。)

函数排列(集合){
var字母表={};
用于(集合中的var s){
如果(!alphabet[set[s]])alphabet[set[s]]=1;
else++字母表[set[s]];
}//字母表={'a':5,'b':2,'r':2,'c':1,'d':1}
perm(“”,set.length);
功能perm(部分,级别){
对于(字母表中的变量a){//字母表中的每个字母
如果(字母[a]){//此字母中有一个或多个可用
--字母表[a];//递减字母计数
if(level>1)perm(part+a,level-1);//与rest一起递归
else document.write(part+a+“
”);//最深递归级别 ++字母表[a];//恢复字母计数 } } } } 排列(['a','b','r','a','c','a','d','a','b','r','a']);//83160唯一排列 //而不是39916800非-
//唯一的加过滤
通常每个置换算法都应该生成
n/(右)结果,但您可以决定实现一个算法,检查重复,这应该很有趣

让我们看看这是否有帮助

def __permutate(self, objectToPermute):
    in_list = []

    for i in range(self.__cur, len(objectToPermute)):
        in_list.append(self.__swap(self.__cur, i, objectToPermute))

    ''' At initial call, self.__cur = 0
       and self.__permSize would be the r in the permutation formula '''
    if self.__cur < self.__permSize - 1:
        self.__cur += 1

        for obj in in_list:
            self.__permutate(obj)

        self.__cur -= 1


    if self.__cur == self.__permSize -1:
        for obj in in_list:
            #this does the job
            if self.norepeat and obj in self.__perm_obj:
                continue
            self.__perm_obj.append(obj[:self.__permSize])
def\uu置换(self,objectToPermute):
in_list=[]
对于范围内的i(self.\u cur,len(objectToPermute)):
in_list.append(self.\u交换(self.\u cur,i,objectToPermute))
初始呼叫时,self.\u cur=0
和self.uu permSize将是置换公式“”中的r
如果self.\u cur
你一定注意到了,我从很久以前写的一个类中提取了这个,这是一个排列算法,我喜欢称之为瓜算法(别介意)

这部分代码所做的只是递归地排列一个对象,交换函数在类中使用,但您可以轻松地将其编码出来。。。现在来看要点,为了避免重复,您所要做的就是确保attrib
self.norepeat=True
和每个重复的对象都将被跳过。如果您需要完整的课程,我很乐意与您分享


我需要一个反馈,以便知道你是否明白我说的话

如果你的字符串包含大量重复字符,那么你可以使用基于组合的算法来生成排列

基本上,这是通过选择一个字母并找到该字母的副本可以到达的所有位置来实现的。有了这些可能性,你就能找到下一个字母的所有位置,依此类推

代码:

这样运行:

for p in perms_without_reps('DDRR'):
    print p
两个重要注意事项:

  • 这不会生成以任何特定方式排序的输出。如果您想要排序输出,请在
    k=
    之前添加
    permutations.sort()
    ,将
    \u helper(idxset-set(pos),i+1)
    替换为
    \u helper(sorted(set(idxset)-set(pos)),i+1)
    并将
    \u helper(set(range(n)),0)
    替换为
    \u helper(list(range(range(n)),0)
    。这将使功能稍微变慢
  • 如果重复次数过多且不平衡,则此函数非常有效。例如,任何基于排列的方法都将永远停留在输入
    'A'*100+'B'*2
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

为什么您不能使用
设置
?它有什么不好?因为我有一个内存错误。我使用的是非常非常非常长的字符串。这是一种设计选择,有一些变通方法,请看:“非常非常长的字符串”不总是会导致不切实际的大输出吗?一个包含两次字母表的52个字符的字符串有超过10^60个排列。我已经回答了这个问题中关于正确性的问题(由弗洛伊德提出)。该算法确实正确,但需要对初始输入进行排序。
for p in perms_without_reps('DDRR'):
    print p