Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 284
Good morning! Here's your coding interview problem for today.

This problem was asked by Yext.

Two nodes in a binary tree can be called cousins if they are on the same level of the tree but have different parents. For example, in the following diagram `4` and `6` are cousins.
```
    1
   / \
  2   3
 / \   \
4   5   6
```
Given a binary tree and a particular node, find all cousins of that node.

Pull request:
Day284
Resolves #578.

Patch:
diff --git a/README.md b/README.md
index e689b52..80baf4d 100644
--- a/README.md
+++ b/README.md
@@ -290,3 +290,4 @@ problems from
 * [Day 281](https://github.com/vaskoz/dailycodingproblem-go/issues/572)
 * [Day 282](https://github.com/vaskoz/dailycodingproblem-go/issues/575)
 * [Day 283](https://github.com/vaskoz/dailycodingproblem-go/issues/577)
+* [Day 284](https://github.com/vaskoz/dailycodingproblem-go/issues/578)
diff --git a/day284/problem.go b/day284/problem.go
new file mode 100644
index 0000000..6373778
--- /dev/null
+++ b/day284/problem.go
@@ -0,0 +1,46 @@
+package day284
+
+// BinaryTree is a binary tree of integers.
+type BinaryTree struct {
+	Value       int
+	Left, Right *BinaryTree
+}
+
+// FindCousins returns all the cousins of a given node.
+func FindCousins(root *BinaryTree, node int) []int {
+	nodeLevel := level(root, node, 1)
+	return levelCousins(root, node, nodeLevel, []int{})
+}
+
+func levelCousins(root *BinaryTree, node, lev int, cousins []int) []int {
+	if root == nil || lev < 2 {
+		return cousins
+	}
+	if lev == 2 {
+		if (root.Left != nil && root.Left.Value == node) ||
+			(root.Right != nil && root.Right.Value == node) {
+			return cousins
+		}
+		if root.Left != nil {
+			cousins = append(cousins, root.Left.Value)
+		}
+		if root.Right != nil {
+			cousins = append(cousins, root.Right.Value)
+		}
+	} else if lev > 2 {
+		cousins = levelCousins(root.Left, node, lev-1, cousins)
+		cousins = levelCousins(root.Right, node, lev-1, cousins)
+	}
+	return cousins
+}
+
+func level(root *BinaryTree, node, lev int) int {
+	if root == nil {
+		return 0
+	} else if root.Value == node {
+		return lev
+	} else if down := level(root.Left, node, lev+1); down != 0 {
+		return down
+	}
+	return level(root.Right, node, lev+1)
+}


Test patch:
diff --git a/day284/problem_test.go b/day284/problem_test.go
new file mode 100644
index 0000000..bba9647
--- /dev/null
+++ b/day284/problem_test.go
@@ -0,0 +1,82 @@
+package day284
+
+import (
+	"reflect"
+	"testing"
+)
+
+// nolint
+var testcases = []struct {
+	root    *BinaryTree
+	node    int
+	cousins []int
+}{
+	{
+		&BinaryTree{
+			1,
+			&BinaryTree{
+				2,
+				&BinaryTree{4, nil, nil},
+				&BinaryTree{5, nil, nil},
+			},
+			&BinaryTree{
+				3,
+				nil,
+				&BinaryTree{6, nil, nil},
+			},
+		},
+		4,
+		[]int{6},
+	},
+	{
+		&BinaryTree{
+			1,
+			&BinaryTree{
+				2,
+				&BinaryTree{4, nil, nil},
+				&BinaryTree{5, nil, nil},
+			},
+			&BinaryTree{
+				3,
+				nil,
+				&BinaryTree{6, nil, nil},
+			},
+		},
+		10,
+		[]int{},
+	},
+	{
+		&BinaryTree{
+			1,
+			&BinaryTree{
+				2,
+				&BinaryTree{4, nil, nil},
+				&BinaryTree{5, nil, nil},
+			},
+			&BinaryTree{
+				3,
+				nil,
+				&BinaryTree{6, nil, nil},
+			},
+		},
+		6,
+		[]int{4, 5},
+	},
+}
+
+func TestFindCousins(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if cousins := FindCousins(tc.root, tc.node); !reflect.DeepEqual(cousins, tc.cousins) {
+			t.Errorf("Expected %v, got %v", tc.cousins, cousins)
+		}
+	}
+}
+
+func BenchmarkFindCousins(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			FindCousins(tc.root, tc.node)
+		}
+	}
+}