将序列转换为lex顺序

时间:2013-09-14 02:16:39

标签: algorithm sequences

我有一个函数可以生成固定数为1的二进制序列(其余为0)。我需要一个函数,它接受一个序列并以字典顺序返回该序列的位置。例如,长度为5且具有3 1的10个序列是

0 0 1 1 1
0 1 0 1 1
0 1 1 0 1
0 1 1 1 0
1 0 0 1 1
1 0 1 0 1
1 0 1 1 0
1 1 0 0 1
1 1 0 1 0
1 1 1 0 0

我需要一个函数,例如0 1 1 0 1并返回3,因为它是列表中的第三个。

我能想到的唯一一个效率太低的方法是生成所有序列(简单),存储它们(占用太多空间),然后在列表中搜索给定的序列(太慢) ,并返回其立场。有更快的方法吗?我看不到一些简单的伎俩?

1 个答案:

答案 0 :(得分:3)

我们使用n 1 k调用长度为binseq(n,k)的序列集。然后可以递归地解决这个问题,如下所示:

  1. 基本情况:如果S长度为1,则位于第1位。
  2. 如果S以0开头,则其位置与tail(S)Sbinseq(n-1, k)移除第一个元素的位置)相同。
  3. 如果S以1开头,则其位置等于tail(S)binseq(n-1, k-1)的位置加上binseq(n-1, k)中的序列数。
  4. 在python代码中:

    #!/usr/bin/env python
    
    def binom(n, k):
        result = 1
        for i in range(1, k+1):
            result = result * (n-i+1) / i
        return result
    
    def lexpos(seq):
        if len(seq) == 1:
            return 1
        elif seq[0] == 0:
            return lexpos(seq[1:])
        else:
            return binom(len(seq)-1, seq.count(1)) + lexpos(seq[1:])
    

    或Abhishek Bansal建议的迭代版本:

    def lexpos_iter(seq):
        pos = 1
        for i in xrange(len(seq)):
            if seq[i] == 1:
                pos += binom(len(seq)-i-1, seq[i:].count(1))
        return pos