如何使用递归查找列表的递增子序列?

时间:2019-06-28 10:08:07

标签: python list

给出一个列表,我想编写一个函数,该函数将返回列表中所有递增的子序列。顺序无关紧要。

例如inc_subseqs([1、3、2])-> [[],[1],[1、2],[1、3],[2],[3]]

我发现了一种类似的方式:

def insert_into_all(item, nested_list):
    """Assuming that nested_list is a list of lists, return a new list
    consisting of all the lists in nested_list, but with item added to
    the front of each.

    >>> nl = [[], [1, 2], [3]]
    >>> insert_into_all(0, nl)
    [[0], [0, 1, 2], [0, 3]]
    """
    return [[item] + el for el in nested_list]

def inc_subseqs(s):
    """Assuming that S is a list, return a nested list of all subsequences
    of S (a list of lists) for which the elements of the subsequence
    are strictly nondecreasing. The subsequences can appear in any order.

    >>> seqs = inc_subseqs([1, 3, 2])
    >>> sorted(seqs)
    [[], [1], [1, 2], [1, 3], [2], [3]]
    >>> inc_subseqs([])
    [[]]
    >>> seqs2 = inc_subseqs([1, 1, 2])
    >>> sorted(seqs2)
    [[], [1], [1], [1, 1], [1, 1, 2], [1, 2], [1, 2], [2]]
    """
    def subseq_helper(s, prev):
        if not s:
            return [[]]
        elif s[0] < prev:
            return subseq_helper(s[1:], prev)
        else:
            a = subseq_helper(s[1:], s[0])  # with first
            b = subseq_helper(s[1:], prev)  # without first
            return insert_into_all(s[0], a) + b
    return subseq_helper(s, 0)

但是,我不知道subseq_helper的其余部分如何工作以及算法的一般流程吗?

2 个答案:

答案 0 :(得分:0)

这是一个树递归问题。

prev存储返回列表的当前最大数目,在elif条件之后,我们知道s [0]> = prev。

进入else条件,我们知道结果可以分为两部分,一个包括s [0],一个不包括s [0],并且这两个部分不共享公共元素。我们知道subseq_helper(s [1:],prev)将产生一个结果min为min(r)> = prev。因此,如果我们包含s [0],则它必须是第一个元素,并且需要将prev替换为s [0]。如果不包含s [0],则prev参数保持不变。然后,我们将两个结果加在一起。

答案 1 :(得分:0)

其余部分的工作方式如下:

让我们说初始序列,s = s [0] s [1] s [2] s [3] ... s [n]。 可以从可以从s [0] s [1] s [2] s [3] ... s [n]中选取的任意数量的s [i]的顺序组合创建seq s的一个子序列。 /> 例如s [0] s [1],s [0] s [1] s [4],s [0] s [7],s [1] s [2] s [6],s [2] s [ 3] s [5]等。 我们可以将所有这些子序列的集合分为两个部分(或两个子集): 一个子集A,具有以s [0]开头的所有子序列(换句话说,包括s [0]),并且 其余不以s [0]开头的子集B(没有s [0],只需在其余s [1:]中选择)。

返回问题,选择s的所有子序列且约束不减。 在子集 A 中,每个子序列都以s [0]开头,并且s [1:]的其余子序列的成员不得小于s [0](非递减)。这导致 a = subseq_helper(s [1:],s [0])。 为了使它们以s [0]开头,我们应用了函数insert_into_all,因此现在得到 A 。 不包含s [0]的另一组子序列,即子集 B ,不需要与s [0]进行比较,因为排除了s [0],但必须进行比较保持不变。 这就是为什么 b = subseq_helper(s [1:],prev),而我们有 B = = b的原因。 因此,else部分返回 A + B ,即insert_to_all(s [0],a)+ b


省略号部分: 给定一定数量的prev,我们要查找(或创建)s [0] s [1] ... s [n]的子序列,条件是s [0]不得小于prev(我们希望它不等于从上一个递减)。如果s [0]小于prev,则跳过s [0],并使用s [1:](其余)。因此,返回subseq_helper(s [1:],prev)。