【问题标题】:converting sequences to lex order将序列转换为 lex 顺序
【发布时间】:2013-09-15 01:26:27
【问题描述】:

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

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,因为它是列表中的第三个。

我能想到的唯一一件效率太低的事情是生成所有序列(简单),存储它们(占用太多空间),然后在列表中搜索给定序列(太慢) ,并返回其位置。有没有更快的方法来做到这一点?一些我看不到的简单技巧?

【问题讨论】:

    标签: algorithm sequences


    【解决方案1】:

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

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

    在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
    

    【讨论】:

    • 好主意!它也可以迭代地完成,例如对于 S = 1010100,位置 = C(6,3) + C(4,2) + C(2,1) + 1 = 29。
    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 2017-06-18
    • 2016-03-31
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    相关资源
    最近更新 更多