about summary refs log tree commit diff
path: root/scratch/facebook/interview-cake/linked-list-cycles.py
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2020-11-21T14·47+0000
committerWilliam Carroll <wpcarro@gmail.com>2020-11-21T14·47+0000
commit70e74a4027a762180840ec79ccec9c8f998a7683 (patch)
tree1235f29af42579806cf2470ef98e93c3ed47e099 /scratch/facebook/interview-cake/linked-list-cycles.py
parentcbdac306433dec51c99cc0b363dcfd8d063f78c3 (diff)
Solve "linked-list-cycles"
Write a predicate for checking if a linked-list contains a cycle. For additional
practice, I also implemented a function that accepts a linked-list containing a
cycle and returns the first element of that cycle.
Diffstat (limited to 'scratch/facebook/interview-cake/linked-list-cycles.py')
-rw-r--r--scratch/facebook/interview-cake/linked-list-cycles.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/scratch/facebook/interview-cake/linked-list-cycles.py b/scratch/facebook/interview-cake/linked-list-cycles.py
new file mode 100644
index 000000000000..523ecd959daf
--- /dev/null
+++ b/scratch/facebook/interview-cake/linked-list-cycles.py
@@ -0,0 +1,70 @@
+def contains_cycle(node):
+    """
+    Return True if the linked-list, `node`, contains a cycle.
+    """
+    if not node:
+        return False
+    a = node
+    b = node.next
+    while a != b:
+        a = a.next
+        if b and b.next and b.next.next:
+            b = b.next.next
+        else:
+            return False
+    return True
+
+################################################################################
+# Bonus
+################################################################################
+
+def first_node_in_cycle(node):
+    """
+    Given that the linked-list, `node`, contains a cycle, return the first
+    element of that cycle.
+    """
+    # enter the cycle
+    a = node
+    b = node.next
+    while a != b:
+        a = a.next
+        b = b.next.next
+
+    # get the length of the cycle
+    beg = a
+    a = a.next
+    n = 1
+    while a != beg:
+        a = a.next
+        n += 1
+
+    # run b n-steps ahead of a
+    a = node
+    b = node
+    for _ in range(n):
+        b = b.next
+
+    # where they intersect is the answer
+    while a != b:
+        a = a.next
+        b = b.next
+    return a
+
+################################################################################
+# Tests
+################################################################################
+
+class Node(object):
+    def __init__(self, value, next=None):
+        self.value = value
+        self.next = next
+    def __repr__(self):
+        return "Node({}) -> ...".format(self.value)
+
+d = Node('d')
+c = Node('c', d)
+b = Node('b', c)
+a = Node('a', b)
+d.next = b
+
+print(first_node_in_cycle(a))