簡體   English   中英

如何使用遞歸查找列表的遞增子序列?

[英]How to find increasing subsequence of a list using recursion?

給定一個列表,我想編寫一個函數來返回列表的所有遞增子序列。 順序無關緊要。

例如 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的 else 部分是subseq_helper工作的以及算法的一般流程?

這是一個樹遞歸問題。

prev 存儲當前返回列表的最大數量,並且經過 elif 條件后,我們知道 s[0] >= prev。

進入else條件,我們知道結果可以分成兩部分,一包含s[0],一不包含,而且這兩部分沒有共同的元素。 我們知道 subseq_helper(s[1:], prev) 將產生具有 min(r) >= prev 的結果 r。 因此,如果我們包含 s[0],它必須是第一個元素,我們需要將 prev 替換為 s[0]。 如果我們不包括 s[0],則 prev 參數保持不變。 然后我們將兩個結果相加。

else 部分的工作方式如下:

假設初始序列,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] 被排除在外,但必須與 prev 進行比較才能不減少. 這就是為什么b = subseq_helper(s[1:], prev) ,我們有B是 = b 。 因此,else 部分返回A + B ,即 insert_to_all(s[0],a) + b


elif 部分:給定一定數量的 prev,我們想要找到(或創建)s[0] s[1] ... s[n] 的子序列,條件是 s[0] 不能小於 prev(我們希望它不比上一個減少)。 如果 s[0] 小於 prev,我們跳過 s[0],並使用 s[1:](剩余的)。 因此,返回 subseq_helper(s[1:], prev)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM