-
Notifications
You must be signed in to change notification settings - Fork 0
/
linked_list.dart
126 lines (108 loc) · 3.12 KB
/
linked_list.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
class LinkedListNode<T> {
final T value;
LinkedListNode next;
LinkedListNode(this.value);
LinkedListNode<T> append(LinkedListNode<T> nextNode) {
next = nextNode;
return nextNode;
}
String toString() {
if (!hasNext) {
return "$value;";
} else {
return "$value -> ${next.toString()}";
}
}
int get length {
if (!hasNext) {
return 1;
} else {
return 1 + next.length;
}
}
LinkedListNode<T> findLoopStart() {
Map<LinkedListNode<T>, bool> occurrences = {};
LinkedListNode<T> runner = this;
while (runner != null) {
if (occurrences.containsKey(runner)) {
return runner;
}
occurrences[runner] = true;
runner = runner.next;
}
return null; // No loop
}
LinkedListNode<T> findLoopStartRunner() {
LinkedListNode<T> slowRunner = this;
LinkedListNode<T> fastRunner = this;
bool collided = false;
while (fastRunner != null && !collided) {
slowRunner = slowRunner.next;
fastRunner = fastRunner.next?.next;
print("R1 - s: ${slowRunner?.value}, f: ${fastRunner?.value}");
if (slowRunner != null && slowRunner == fastRunner) {
collided = true;
}
}
if (!collided) {
return null;
}
slowRunner = this; // Move slowRunner back to the head
while (slowRunner != fastRunner) {
print("R2 - s: ${slowRunner?.value}, f: ${fastRunner?.value}");
slowRunner = slowRunner.next;
fastRunner = fastRunner.next;
}
return slowRunner;
}
bool get hasNext => next != null;
static LinkedListNode<T> mergeSort<T extends Comparable>(
LinkedListNode<T> head) {
if (head == null || head.length == 1) {
return head;
}
SplitLinkedList<T> splitLists = LinkedListNode.split(head);
LinkedListNode sortedA = LinkedListNode.mergeSort(splitLists.a);
LinkedListNode sortedB = LinkedListNode.mergeSort(splitLists.b);
return LinkedListNode.sortedMerge(sortedA, sortedB);
}
static LinkedListNode<T> sortedMerge<T extends Comparable>(
LinkedListNode<T> headA, LinkedListNode<T> headB) {
if (headA == null) {
return headB;
}
if (headB == null) {
return headA;
}
if (headA.value.compareTo(headB.value) < 0) {
headA.next = sortedMerge(headA.next, headB);
return headA;
} else {
headB.next = sortedMerge(headA, headB.next);
return headB;
}
}
static SplitLinkedList<T> split<T>(LinkedListNode<T> headOriginal) {
assert(headOriginal != null);
int lengthO = headOriginal.length;
int lengthA = lengthO ~/ 2; //implicitely round down
LinkedListNode headA = headOriginal;
LinkedListNode headB = headOriginal;
LinkedListNode workingNode = headOriginal;
for (int i = 0; i < lengthO; i++) {
if (i == lengthA - 1) {
headB = workingNode.next;
workingNode.next = null;
headA = headOriginal;
return new SplitLinkedList(headA, headB);
}
workingNode = workingNode.next;
}
return null;
}
}
class SplitLinkedList<T> {
final LinkedListNode<T> a;
final LinkedListNode<T> b;
SplitLinkedList(this.a, this.b);
}