【问题标题】:permutation ranking with DI sequenceDI序列的排列排序
【发布时间】:2019-10-26 07:59:22
【问题描述】:

我想通过长度给定的排列子集进行排名和取消排名。子集定义如下:

排列长度为 4 的示例:

我们的输入位串长度为 3(总是排列长度 - 1)

010

0 表示两个连续的元素是Increasing。

1 表示 2 个连续的元素是 Decreasing。

对于此位串,存在具有以下排列的子集:1324,1423,2314,2413,3412

我想要排名和取消排名的位串定义的排列子集?给定的位串是否有一种算法方法可以做到这一点?

【问题讨论】:

    标签: arrays algorithm combinations permutation ranking


    【解决方案1】:

    让我重申我认为你的意思的问题。

    您有一个长度为n-1 的位串。如果它的数字是增加/减少的模式,则描述了一组适合该模式的排列。该集合可以按升序排列。

    你希望能够解决两个问题。

    1. 给定一个适合模式的排列,说出它在该顺序中的位置(即“排列”它)
    2. 给定一个数字,产生在该位置的排列顺序(即“取消排序”它)

    理想情况下,您希望能够解决这些问题,而不必生成所有符合模式的排列。

    两者的关键在于以下功能:

    def count_matching (bitstring, start):
        ''' Returns how many permutations of 1..(len(bitstring) + 1)
        ''' match bitstring with starting value start
        # some implementation here.
    

    这可以很容易地递归计算。然而,以天真的方式这样做会产生所有排列。但是,如果我们给memoize 添加一个缓存层,那么我们会存储多项式数量的数据并进行多项式调用来填充它。

    这是为您的示例缓存后获得的数据:

    {
        ('010', 1): 2,
        ('010', 2): 2,
        ('010', 3): 1,
        ('010', 4): 0,
        ('10', 1): 0,
        ('10', 2): 1,
        ('10', 3): 1,
        ('0', 1): 1,
        ('0', 2): 0,
        ('', 1): 1
    }
    

    现在这似乎是针对少数模式的大量数据。但是对于长度为n 的排列,条目的数量会像O(n^2) 一样增长,并且填充它的调用数量会像O(n^3) 一样增长。 (任何眼尖的读者都可能想出如何及时填充它O(n^2)。我将使用简单版本。)


    有了这个,我们可以根据以下想法进行排名并确定它必须是哪种排列。

    假设我们想要找到秩为 4 的排列。我们的起始号码列表是(1 2 3 4)。我们可以跳过以('010', 1) 开头的0 个排列,答案将是('010', 2) 的2 个排列中的第二个。

    取第二个数字2,我们的部分排列是[2,我们有数字(1 3 4)。我们正在寻找位串'10' 的第二个。我们跳过以('10', 1) 开头的0 个排列,以('10', 2) 开头的1,并希望以('10', 3) 开头的1 中的第一个。

    取第三个数字4,我们的部分排列是[2, 4,我们有数字(1 3)。和之前一样,我们发现我们想要('0', 1) 中的第一个。

    取第一个数字1,我们的部分排列是[2, 4, 1,我们有数字(3)。选择不多。

    所以我们完成并得到[2, 4, 1, 3]。您可以验证的是第 4 个。

    所以我们以[2, 4, 3, 1] 结束。


    我们也可以走另一条路。采用相同的排列,我们从[2, 4, 3, 1] 开始并想要它的排名。

    在它之前有多少位在第一位不同?它使用了第二个可能的第一个数字。从 ('010', 1) 的条目我们知道有 2 个。剩下的数字是 1 3 4

    它前面有多少个第二位数不同?它使用第三个可能的第二个数字。从 ('10', 1)('10', 2) 的条目中,我们知道它前面还有 1 个。

    我们现在有号码1 3。第三位数字没有出现在它之前。再一次,最后没有。

    前面有3,它必须有等级4。


    你有它。为了记忆一个递归函数,您现在可以直接按等级查找排列,或对给定排列进行排序。

    【讨论】:

    • 谢谢,您能否提供更多信息,如何在O(n^2) 时间建立数据结构?还是其他优化?
    • 我如何向前或向后构建数据结构?意味着我是从上到下构建还是ver visa?
    • @TThoEinthausend 很抱歉没有回来。我建议编写一个递归函数然后进行记忆,所以从上到下编写你的递归。对于高效版本,您必须在每个剩余长度的位串上计算给定start 的所有计数,然后计算来自1..startstart..(len(bitstring)+1) 的计数的累积总和。这些都是O(n) 操作。现在,当您进入下一个更高级别时,您遇到的总和都是预先计算的,O(1) 查找而不是 O(n) 计算也是如此。
    • Np,好的,我已经完成了,工作正常,除了位串 010013245 我得到排名 2。还填充数据结构需要很长时间我使用 @987654363 的调整算法@ 使用 DFS 需要更长的时间。我认为瓶颈是填充数据结构而不是最终求和。
    • 我想知道是否有一种使用二项式进行排名的解决方案,例如第二个解决方案中描述的https://leetcode.com/articles/valid-permutations-for-di-sequence/,用于计算烫发总数?
    猜你喜欢
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 2019-03-10
    • 2014-06-02
    • 1970-01-01
    相关资源
    最近更新 更多