Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 169
Good morning! Here's your coding interview problem for today.

This problem was asked by Google.

Given a linked list, sort it in O(n log n) time and constant space.

For example, the linked list `4 -> 1 -> -3 -> 99` should become `-3 -> 1 -> 4 -> 99`.

Pull request:
Day169
Resolves #352.

Patch:
diff --git a/README.md b/README.md
index b2e55e4..84efb38 100644
--- a/README.md
+++ b/README.md
@@ -180,4 +180,5 @@ problems from
 * [Day 166](https://github.com/vaskoz/dailycodingproblem-go/issues/346)
 * [Day 167](https://github.com/vaskoz/dailycodingproblem-go/issues/347)
 * [Day 168](https://github.com/vaskoz/dailycodingproblem-go/issues/348)
+* [Day 169](https://github.com/vaskoz/dailycodingproblem-go/issues/352)
 * [Day 170](https://github.com/vaskoz/dailycodingproblem-go/issues/353)
diff --git a/day169/problem.go b/day169/problem.go
new file mode 100644
index 0000000..16511bc
--- /dev/null
+++ b/day169/problem.go
@@ -0,0 +1,60 @@
+package day169
+
+// SinglyLL is a singly linked list of integers.
+type SinglyLL struct {
+	Value int
+	Next  *SinglyLL
+}
+
+// MergesortSinglyLinkedList runs in O(N log N) time and O(1) space.
+func MergesortSinglyLinkedList(head *SinglyLL) *SinglyLL {
+	var size int
+	ptr := head
+	for ptr != nil {
+		size++
+		ptr = ptr.Next
+	}
+	if size == 1 {
+		return head
+	}
+	ptr = head
+	for i := 0; i < (size/2)-1; i++ {
+		ptr = ptr.Next
+	}
+	half := ptr.Next
+	ptr.Next = nil
+	a := MergesortSinglyLinkedList(head)
+	b := MergesortSinglyLinkedList(half)
+	return mergeSorted(a, b)
+}
+
+func mergeSorted(a, b *SinglyLL) *SinglyLL {
+	result := &SinglyLL{}
+	ptr := result
+	for a != nil || b != nil {
+		if a != nil && b != nil {
+			if a.Value < b.Value {
+				ptr.Next = a
+				a = a.Next
+				ptr = ptr.Next
+				ptr.Next = nil
+			} else {
+				ptr.Next = b
+				b = b.Next
+				ptr = ptr.Next
+				ptr.Next = nil
+			}
+		} else if a != nil {
+			ptr.Next = a
+			a = a.Next
+			ptr = ptr.Next
+			ptr.Next = nil
+		} else if b != nil {
+			ptr.Next = b
+			b = b.Next
+			ptr = ptr.Next
+			ptr.Next = nil
+		}
+	}
+	return result.Next
+}


Test patch:
diff --git a/day169/problem_test.go b/day169/problem_test.go
new file mode 100644
index 0000000..2d946a6
--- /dev/null
+++ b/day169/problem_test.go
@@ -0,0 +1,52 @@
+package day169
+
+import "testing"
+
+var testcases = []struct {
+	input    *SinglyLL
+	expected *SinglyLL
+}{
+	{&SinglyLL{4, &SinglyLL{1, &SinglyLL{-3, &SinglyLL{99, nil}}}},
+		&SinglyLL{-3, &SinglyLL{1, &SinglyLL{4, &SinglyLL{99, nil}}}}},
+}
+
+func TestMergesortSinglyLinkedList(t *testing.T) {
+	t.Parallel()
+	for tcid, tc := range testcases {
+		input := copySinglyLL(tc.input)
+		if result := MergesortSinglyLinkedList(input); !equal(result, tc.expected) {
+			t.Errorf("Lists don't match for tcid%d", tcid)
+		}
+	}
+}
+
+func BenchmarkMergesortSinglyLinkedList(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			input := copySinglyLL(tc.input)
+			MergesortSinglyLinkedList(input)
+		}
+	}
+}
+
+func copySinglyLL(a *SinglyLL) *SinglyLL {
+	result := &SinglyLL{}
+	ptr := result
+	for a != nil {
+		ptr.Next = &SinglyLL{a.Value, nil}
+		ptr = ptr.Next
+		a = a.Next
+	}
+	return result.Next
+}
+
+func equal(a, b *SinglyLL) bool {
+	for a != nil && b != nil {
+		if a.Value != b.Value {
+			return false
+		}
+		a = a.Next
+		b = b.Next
+	}
+	return a == nil && b == nil
+}