求樹中兩個節點的最低公共祖先節點(go)
阿新 • • 發佈:2018-11-05
該題目有以下幾種情況可以考慮
1. 樹是二叉搜尋樹,二叉搜尋樹的特點是根節點值大於所有左子樹節點值,小於所有右子樹節點值,則最低公共祖先即該節點值大於給定兩個節點中的一個值,小於另外一個節點的值,go程式碼實現如下
type TreeNode struct { Val int Left *TreeNode Right *TreeNode } // 如果樹是二叉搜尋樹 func getLastCommentNode(node1, node2, root *TreeNode) *TreeNode { if nil == root || nil == node1 || nil == node2 { return nil } if node1.Val < root.Val && node2.Val < root.Val { return getLastCommentNode(node1, node2, root.Left) } if node1.Val > root.Val && node2.Val > root.Val { return getLastCommentNode(node1, node2, root.Right) } return root }
2. 樹是普通二叉樹,但節點有指向父節點的指標,則該問題轉化為了求兩個連結串列第一個相交的節點, go程式碼實現如下
type TreeNode1 struct { Val int Child []*TreeNode1 Parent *TreeNode1 } // 帶有父指標的普通樹 func getLastCommentNode(node1, node2 *TreeNode1) *TreeNode1 { len1 := getLengthToRoot(node1) len2 := getLengthToRoot(node2) if len1 > len2 { for i := 0; i < len1 - len2; i++ { node1 = node1.Parent } } else if len1 < len2 { for i := 0; i < len2 - len1; i++ { node2 = node2.Parent } } for node1 != nil && node2 != nil { if node1.Parent == node2.Parent { return node1.Parent } node1 = node1.Parent node2 = node2.Parent } return nil } func getLengthToRoot(node *TreeNode1) int { if node == nil { return 0 } return 1 + getLengthToRoot(node.Parent) }
3. 如果該樹為普通樹,且沒有指向父節點的指標,則該問題可以轉化成一下方式求解:a. 如果給定的兩個節點都在當前節點同一個孩子的節點下面,則當前節點變成當前節點的孩子節點;b. 如果給定的兩個節點在當前節點不同的孩子節點下面,則當前節點就是最低公共祖先,程式碼實現分為遞迴和非遞迴
遞迴實現(go):
type TreeNode2 struct { Val int Child []*TreeNode2 } // 普通樹 遞迴實現 func getLastComentNode(node1, node2, root *TreeNode2) *TreeNode2 { if root == nil { return nil } found1, local1 := findNodeAndLocal(node1, root) found2, local2 := findNodeAndLocal(node2, root) if !found2 || !found1 { return nil } if local2 == local1 { return getLastComentNode(node1, node2, root.Child[local1]) } return root } func findNode(node, root *TreeNode2) (bool) { if root == nil { return false } if root == node { return true } found := false for i := 0; i < len(root.Child) && !found; i++ { found = findNode(node, root.Child[i]) } return found } func findNodeAndLocal(node, root *TreeNode2) (bool, int) { if root == nil { return false, -1 } found := false local := -1 for i := 0; i < len(root.Child) && !found; i++ { found = findNode(node, root.Child[i]) if found { local = i } } return found, local }
非遞迴實現(go):
//普通樹 非遞迴實現
func getLastComentNode(node1, node2, root *TreeNode2) *TreeNode2 {
path1 := list.New()
path2 := list.New()
if nil == root || nil == node1 || nil == node2 {
return nil
}
getPath(node1, root, path1)
getPath(node2, root, path2)
var lastParentNode *TreeNode2
for path1.Front() != nil && path2.Front() != nil {
if path1.Front().Value == path2.Front().Value {
lastParentNode = path1.Front().Value.(*TreeNode2)
}
path1.Remove(path1.Front())
path2.Remove(path2.Front())
}
return lastParentNode
}
func getPath(node, root *TreeNode2, path *list.List) bool {
if node == root {
return true
}
path.PushBack(root)
found := false
for i:= 0; i < len(root.Child) && !found; i++ {
found = getPath(node, root.Child[i], path)
}
if !found {
path.Remove(path.Back())
}
return found
}
var c = &TreeNode2{Val: 3}
var d = &TreeNode2{Val: 4}
var e = &TreeNode2{Val: 5}
var b = &TreeNode2{Val: 2, Child: []*TreeNode2{d, e}}
var a = &TreeNode2{Val: 1, Child: []*TreeNode2{b, c}}
func TestTree(t *testing.T) {
temp := getLastComentNode(b, e, a)
fmt.Println(temp)
}