diff --git a/README.md b/README.md index 42c5099..2365712 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ Binary Trees |--------------------------------------------------------------------------|:------------:|:-----------:| | [Test if a binary tree is balanced][144] | [tests][145] | ✓ | | [Test if a binary tree is symmetric][146] | [tests][147] | ✓ | -| [Compute the lowest common ancestor in a binary tree][148] | [tests][149] | | +| [Compute the lowest common ancestor in a binary tree][148] | [tests][149] | ✓ | | [Compute the LCA when nodes have parent pointers][150] | [tests][151] | | | [Sum the root-to-leaf paths in a binary tree][152] | [tests][153] | | | [Find a root to leaf path with specified sum][154] | [tests][155] | | @@ -544,8 +544,8 @@ Honors Class [145]: btrees/balanced_test.go [146]: btrees/symmetric.go [147]: btrees/symmetric_test.go -[148]: in_progress.md -[149]: in_progress.md +[148]: btrees/lca.go +[149]: btrees/lca_test.go [150]: in_progress.md [151]: in_progress.md [152]: in_progress.md diff --git a/btrees/lca.go b/btrees/lca.go new file mode 100644 index 0000000..0b3b5e7 --- /dev/null +++ b/btrees/lca.go @@ -0,0 +1,43 @@ +// Copyright (c) 2015, Peter Mrekaj. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE.txt file. + +package btrees + +// findLCA walks the binary tree t and returns lowest common +// ancestor for the nodes n0 and n1. The cnt is 0, 1, or 2 +// depending on nodes (n0, n1) presented in the tree. +func findLCA(t, n0, n1 *BTree) (cnt int, ancestor *BTree) { + if t == nil { + return 0, nil // Base case. + } + + // Postorder walk. + lc, la := findLCA(t.right, n0, n1) + if lc == 2 { + return lc, la + } + rc, ra := findLCA(t.left, n0, n1) + if rc == 2 { + return rc, ra + } + + cnt = lc + rc + if t == n0 { + cnt++ + } + if t == n1 { + cnt++ + } + if cnt == 2 { + ancestor = t + } + return cnt, ancestor +} + +// LCA returns the lowest common ancestor in +// the binary tree t for the nodes n0, n1. +func LCA(t, n0, n1 *BTree) *BTree { + _, a := findLCA(t, n0, n1) + return a +} diff --git a/btrees/lca_test.go b/btrees/lca_test.go new file mode 100644 index 0000000..3f47fec --- /dev/null +++ b/btrees/lca_test.go @@ -0,0 +1,45 @@ +// Copyright (c) 2015, Peter Mrekaj. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE.txt file. + +package btrees + +import "testing" + +func TestLCA(t *testing.T) { + // A Binary Tree of height 5. + tree := &BTree{"A", + &BTree{"B", + &BTree{"C", + &BTree{"D", nil, nil}, + &BTree{"E", nil, nil}}, + &BTree{"F", + nil, + &BTree{"G", + &BTree{"H", nil, nil}, + nil}}}, + &BTree{"I", + &BTree{"J", + nil, + &BTree{"K", + &BTree{"L", + nil, + &BTree{"M", nil, nil}}, + &BTree{"N", nil, nil}}}, + &BTree{"O", + nil, + &BTree{"P", nil, nil}}}} + + for _, test := range []struct { + t, n0, n1 *BTree + want *BTree + }{ + {&BTree{"TREE", nil, nil}, nil, nil, nil}, + {tree, tree.left, tree.right, tree}, // n0 = B; n1 = I; want = A + {tree, tree.right.left.right.left.right, tree.right.left.right.right, tree.right.left.right}, // n0 = M; n1 = N; want = K + } { + if got := LCA(test.t, test.n0, test.n1); got != test.want { + t.Errorf("LCA(%v, %v, %v) = %v; want %v", test.t, test.n0, test.n1, got, test.want) + } + } +}