diff options
Diffstat (limited to 'users/wpcarro/scratch/facebook/interview-cake/linked-list-cycles.py')
-rw-r--r-- | users/wpcarro/scratch/facebook/interview-cake/linked-list-cycles.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/users/wpcarro/scratch/facebook/interview-cake/linked-list-cycles.py b/users/wpcarro/scratch/facebook/interview-cake/linked-list-cycles.py new file mode 100644 index 000000000000..523ecd959daf --- /dev/null +++ b/users/wpcarro/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)) |