最長同值路徑

pardon110發表於2020-12-29

題面

給定一個二叉樹,找到最長的路徑,這個路徑中的每個節點具有相同值。 這條路徑可以經過也可以不經過根節點。
兩個節點之間的路徑長度由它們之間的邊數表示,下面輸出 2

              5
             / \
            4   5
           / \   \
          1   1   5

分析

  • 將不同值樹拆解成多個同值子樹,求各子樹的最大路徑,取長
  • 確定同值子樹的根節點,同值樹的參照值,如示例層序遍歷中選用第一個5為同值子樹根,而非下層5
  • 遞迴求同值樹單邊最大路徑,遞迴體內比較取該同值樹最長路徑,對於同值樹而言最長路徑必經過根節點

拆解

不同值樹拆解為同值子樹過程

最長同值路徑
上述拆解,參考標準值依次為5,4,1,1, 上層向下層帶值傳遞,父子不同拆分

同值子樹最大路徑,必經過根節點
最長同值路徑
每個同值連續節點最長路徑,即左路徑最長+右最長

程式碼

func longestUnivaluePath(root *TreeNode) int {
    var rs int
    var dfs func(*TreeNode,int) int
    dfs = func(root *TreeNode, val int) int{
        if root.Val != val {    // 隱性表達該條件體外,當前節點值與參照標準值相等
            dfs(root,root.Val)  // 選定拆解為同值節點子樹根節點,及同值參照物
            return -1           // 修正同值連續節點遞迴+1帶來的副作用
        }

        l,r:= 0,0
        if root.Left != nil {
            l = dfs(root.Left, val)+1  // 父子左連續,假定左值與參照值相同,計數加1
        }
        if root.Right != nil {
            r= dfs(root.Right, val)+1  // 右連續計數
        }

        if cur := l+r; cur > rs {  // 最大連續路徑數
            rs = cur
        }
        if l > r {  // 取單邊連續最大值
            return l
        }
        return r
    }
    if root != nil {
        dfs(root, root.Val)
    }
    return rs
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章