确定任意可重复集合某一排列的字典序

(1) 首先考虑某一个不重复集合的排列字典序。这很容易比较,只需找出有多少种排列小于它既可。从第一个元素x开始遍历,不妨假设后面的元素有i个小于x,那么一共有i*(n-1)!种情况。假如没有,则需要保持第一个元素不动,类似的方式判断第二个元素。最后将所有的种类加起来既可

(2) 假如有重复的元素,那么问题将会变得复杂很多。按照(1)的思路继续,我们假设第一个x后有j个元素小于x,那么我们必须要不重复的计算情况,既后j个元素中不重复访问。其次,选定一个元素并与x交换后,考虑有多少种排列小于当前排列: (n1)!/iA(ii) ,其中i代表后j个元素中某一个元素的重复个数。

(3) 最后为了拓展性,设计了一个key_value函数和参数key函数,用来确定比较值。

def encode_2(n,key=None,unique = False):
    fact = [1]
    for i in range(1,n+1):fact.append(fact[-1]*i)
    def key_value(x):return key(x) if key else x
    def encode_unique(s):
        length = len(s)
        code = 0
        for i in range(length):
            count=0
            for j in range(i+1,length):
                if key_value(s[i])>key_value(s[i]):count+=1
            code += count*fact[length-i-1]
        return code
    def encode_nonunique(s):
        length = len(s)
        code,repeat = 0,{}
        for x in s:
            k = key_value(x)
            if k in repeat:repeat[k]+=1
            else:repeat[k]=1
        for i in range(length):
            repeat[key_value(s[i])]-=1
            vis = set()
            for j in range(i+1,length):
                if key_value(s[i])>key_value(s[j]) and key_value(s[j]) not in vis:
                    repeat[key_value(s[j])]-=1;repeat[key_value(s[i])]+=1
                    code += fact[length-i-1]//reduce(lambda x,y:x*y,[w for w in repeat.values() if w>1],1)
                    repeat[key_value(s[j])]+=1;repeat[key_value(s[i])]-=1
                    vis.add(key_value(s[j]))
        return code
    return encode_unique if unique else encode_nonunique
hash = encode_2(10)
print(hash([1,3,2,2,1,1,6,7,8]))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值