Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 179
Good morning! Here's your coding interview problem for today.

This problem was asked by Google.

Given the sequence of keys visited by a postorder traversal of a binary search tree, reconstruct the tree.

For example, given the sequence `2, 4, 3, 8, 7, 5`, you should construct the following tree:
```
    5
   / \
  3   7
 / \   \
2   4   8
```

Pull request:
Day179
Resolves #371.

Patch:
diff --git a/README.md b/README.md
index 7d0b448..ebf0a1e 100644
--- a/README.md
+++ b/README.md
@@ -189,3 +189,4 @@ problems from
 * [Day 176](https://github.com/vaskoz/dailycodingproblem-go/issues/364)
 * [Day 177](https://github.com/vaskoz/dailycodingproblem-go/issues/365)
 * [Day 178](https://github.com/vaskoz/dailycodingproblem-go/issues/367)
+* [Day 179](https://github.com/vaskoz/dailycodingproblem-go/issues/371)
diff --git a/day179/problem.go b/day179/problem.go
new file mode 100644
index 0000000..4553ff3
--- /dev/null
+++ b/day179/problem.go
@@ -0,0 +1,51 @@
+package day179
+
+const maxInt = int(^uint(0) >> 1)
+const minInt = -maxInt - 1
+
+// BinaryTree is a binary tree of integers.
+type BinaryTree struct {
+	Value       int
+	Left, Right *BinaryTree
+}
+
+// BuildTreeFromPostorder reconstructs a binary tree from
+// a postorder traversal.
+// Runs in O(N^2) time.
+func BuildTreeFromPostorder(lst []int) *BinaryTree {
+	if len(lst) == 0 {
+		return nil
+	}
+	root := &BinaryTree{lst[len(lst)-1], nil, nil}
+	lst = lst[:len(lst)-1]
+	i := len(lst) - 1
+	for ; i >= 0 && lst[i] > root.Value; i-- {
+	}
+	root.Left = BuildTreeFromPostorder(lst[:i+1])
+	root.Right = BuildTreeFromPostorder(lst[i+1:])
+	return root
+}
+
+// BuildTreeFromPostorderLinear reconstructs a binary tree from
+// a postorder traversal.
+// Runs in O(N) time.
+func BuildTreeFromPostorderLinear(lst []int) *BinaryTree {
+	return buildTreeFromPostorderLinear(&lst, minInt, maxInt)
+}
+
+func buildTreeFromPostorderLinear(lst *[]int, min, max int) *BinaryTree {
+	if len(*lst) == 0 {
+		return nil
+	}
+	var root *BinaryTree
+	key := (*lst)[len(*lst)-1]
+	if key > min && key < max {
+		root = &BinaryTree{key, nil, nil}
+		*lst = (*lst)[:len(*lst)-1]
+		if len(*lst) > 0 {
+			root.Right = buildTreeFromPostorderLinear(lst, key, max)
+			root.Left = buildTreeFromPostorderLinear(lst, min, key)
+		}
+	}
+	return root
+}


Test patch:
diff --git a/day179/problem_test.go b/day179/problem_test.go
new file mode 100644
index 0000000..448ca66
--- /dev/null
+++ b/day179/problem_test.go
@@ -0,0 +1,83 @@
+package day179
+
+import "testing"
+
+var testcases = []struct {
+	postorder []int
+	expected  *BinaryTree
+}{
+	{[]int{2, 4, 3, 8, 7, 5}, &BinaryTree{
+		5,
+		&BinaryTree{
+			3,
+			&BinaryTree{2, nil, nil},
+			&BinaryTree{4, nil, nil},
+		},
+		&BinaryTree{
+			7,
+			nil,
+			&BinaryTree{8, nil, nil},
+		},
+	}},
+	{[]int{1, 7, 5, 50, 40, 10}, &BinaryTree{
+		10,
+		&BinaryTree{
+			5,
+			&BinaryTree{1, nil, nil},
+			&BinaryTree{7, nil, nil},
+		},
+		&BinaryTree{
+			40,
+			nil,
+			&BinaryTree{50, nil, nil},
+		},
+	}},
+	{[]int{}, nil},
+}
+
+func TestBuildTreeFromPostorder(t *testing.T) {
+	t.Parallel()
+	for tcid, tc := range testcases {
+		if result := BuildTreeFromPostorder(tc.postorder); !equal(result, tc.expected) {
+			t.Errorf("Trees don't match for tcid%d", tcid)
+		}
+	}
+}
+
+func BenchmarkBuildTreeFromPostorder(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			BuildTreeFromPostorder(tc.postorder)
+		}
+	}
+}
+
+func TestBuildTreeFromPostorderLinear(t *testing.T) {
+	t.Parallel()
+	for tcid, tc := range testcases {
+		if result := BuildTreeFromPostorderLinear(tc.postorder); !equal(result, tc.expected) {
+			t.Errorf("Trees don't match for tcid%d", tcid)
+		}
+	}
+}
+
+func BenchmarkBuildTreeFromPostorderLinear(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			BuildTreeFromPostorderLinear(tc.postorder)
+		}
+	}
+}
+
+func equal(a, b *BinaryTree) bool {
+	if a == nil && b != nil {
+		return false
+	} else if a != nil && b == nil {
+		return false
+	} else if a == nil && b == nil {
+		return true
+	} else if a.Value != b.Value {
+		return false
+	}
+	return equal(a.Left, b.Left) && equal(a.Right, b.Right)
+}