簡體   English   中英

在從兩個目標節點開始遍歷祖先樹時,我可以標記我在遞歸調用中看到的節點以找到它們的最低共同祖先嗎?

[英]While traversing an ancestor tree starting from two target nodes, can I mark nodes I've seen in recursive calls to find their lowest common ancestor?

我正在解決一個問題,我們在樹中獲得了一tree 、它的roottwo target nodesdescendantOnedescendantTwo )。

我被要求返回兩個目標節點的lowest common ancestor

然而,我們也被告知我們的樹是AncestralTree的一個實例,它由下式給出:

class AncestralTree:
    def __init__(self, name):
        self.name = name
        self.ancestor = None

即對於樹中的每個節點,我們只有向上指向父節點的指針(與具有從父節點到子節點的指針的普通樹相反!)

我解決這個問題的想法是從兩個目標節點開始向上移動,標記我們訪問的每個節點。 在某一時刻,我們必然會訪問一個節點兩次,而我們第一次訪問——這是我們最低的共同祖先!

這是我的代碼:

def getYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo):
    lowestCommonAncestor = None
    
    def checkAncestors(topAncestor,descendantOne, descendantTwo,descendantOneSeen,descendantTwoSeen): 
        if descendantOneSeen and descendantTwoSeen: 
            return descendantOne
        else: 
            return None
        
    while not lowestCommonAncestor:
        **lowestCommonAncestor = checkAncestors(topAncestor,descendantOne.ancestor, descendantTwo,True,False)
        if lowestCommonAncestor: 
            break
        **lowestCommonAncestor = checkAncestors(topAncestor,descendantOne, descendantTwo.ancestor,False,True)
        if descendantOne.ancestor == topAncestor: 
            pass 
        else: 
            descendantOne = descendantOne.ancestor 
        if descendantTwo.ancestor == topAncestor: 
            pass
        else:
            descendantTwo= descendantTwo.ancestor
        
    return lowestCommonAncestor

我在代碼中的兩個recursion calls旁邊放了星 **,因為我相信這是問題所在。

當我運行遞歸調用時,例如說我們已經看到了descendantOne ,當我對descendantTwo運行遞歸調用時,它會在其遞歸調用中自動將descendantOneSeen標記為 false。 所以這導致我們永遠不會讓descendantOneSeendescendantTwoSeen為真。

當我運行上面的代碼時,我確實得到了一個無限循環錯誤——我明白了為什么。

有沒有辦法在不使用global variables的情況下修改我的代碼以實現我想要的?

事實上,它不會那樣工作,因為descendantOneSeen and descendantTwoSeen永遠不會是真的。 但是,即使您修復了這部分邏輯,兩個節點與其最低共同祖先的距離也可能相距甚遠......所以您需要一種不同的算法。

一種方法是像您一樣一起走到樹的頂部,但是當您到達頂部時,繼續在另一個起始節點處引用該引用。 當兩個引用都進行了向下跳轉時,它們在共同的最低祖先處相遇時將訪問完全相同數量的節點。

這導致了一個非常簡單的算法:

def getYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo):
    nodeOne = descendantOne
    nodeTwo = descendantTwo
    while nodeOne is not nodeTwo:
        nodeOne = descendantTwo if nodeOne.ancestor is topAncestor else nodeOne.ancestor
        nodeTwo = descendantOne if nodeTwo.ancestor is topAncestor else nodeTwo.ancestor 
    return nodeOne

這可能看起來很狡猾,因為這些節點引用將永遠相等似乎是幸運的問題。 但是nodeOnenodeTwo引用都將從兩個起點( descendantOnedescendantTwo )開始——只是它們執行此操作的順序是顛倒的。 但這仍然意味着它們在第二次訪問共同祖先時將訪問相同數量的節點。

暫無
暫無

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

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