Skip to content

Instantly share code, notes, and snippets.

@Clivern
Created March 21, 2021 18:42
Show Gist options
  • Save Clivern/232d8bf9b9a0ff30e3339d9c8c086600 to your computer and use it in GitHub Desktop.
Save Clivern/232d8bf9b9a0ff30e3339d9c8c086600 to your computer and use it in GitHub Desktop.
Python Linked Lists
import bisect
from heapq import *
"""
Linked Lists
A linked list is an ordered collection of values.
Linked lists are similar to arrays in the sense that they contain objects in a linear order.
However they differ from arrays in their memory layout.
Arrays are contiguous data structures and they’re composed of fixed-size data records stored in adjoining blocks of memory.
Linked lists, however, are made up of data records linked together by pointers.
https://dbader.org/blog/python-linked-list
"""
class SListNode():
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __repr__(self):
return repr(self.data)
class DListNode():
"""
A node in a doubly-linked list.
"""
def __init__(self, data=None, prev=None, next=None):
self.data = data
self.prev = prev
self.next = next
def __repr__(self):
return repr(self.data)
class SinglyLinkedList:
def __init__(self):
"""
Create a new singly-linked list.
Takes O(1) time.
"""
self.head = None
def __repr__(self):
"""
Return a string representation of the list.
Takes O(n) time.
"""
nodes = []
curr = self.head
while curr:
nodes.append(repr(curr))
curr = curr.next
return '[' + ', '.join(nodes) + ']'
def prepend(self, data):
"""
Insert a new element at the beginning of the list.
Takes O(1) time.
"""
self.head = SListNode(data=data, next=self.head)
def append(self, data):
"""
Insert a new element at the end of the list.
Takes O(n) time.
https://www.hackerrank.com/challenges/30-linked-list/problem
"""
if not self.head:
self.head = SListNode(data=data)
return
curr = self.head
while curr.next:
curr = curr.next
curr.next = SListNode(data=data)
def insert(self, data):
"""
Insert a new element at the end of the list.
Takes O(n) time.
"""
if not self.head:
self.head = SListNode(data=data)
return
curr = self.head
while curr.next:
curr = curr.next
curr.next = SListNode(data=data)
def find(self, key):
"""
Search for the first element with `data` matching
`key`. Return the element or `None` if not found.
Takes O(n) time.
"""
curr = self.head
while curr and curr.data != key:
curr = curr.next
return curr # Will be None if not found
def remove(self, key):
"""
Remove the first occurrence of `key` in the list.
Takes O(n) time.
"""
# Find the element and keep a
# reference to the element preceding it
curr = self.head
prev = None
while curr and curr.data != key:
prev = curr
curr = curr.next
# Unlink it from the list
if prev is None:
self.head = curr.next
elif curr:
prev.next = curr.next
curr.next = None
def reverse(self):
"""
Reverse the list in-place.
Takes O(n) time.
"""
curr = self.head
prev_node = None
next_node = None
while curr:
next_node = curr.next
curr.next = prev_node
prev_node = curr
curr = next_node
self.head = prev_node
def remove_duplicates(self):
"""
Your remove_duplicates function should return the head of the updated linked list. after removing duplicates
https://www.hackerrank.com/challenges/30-linked-list-deletion/problem
"""
if not self.head:
return None
n = self.head
while n.next:
if n.data == n.next.data:
n.next = n.next.next
else:
n = n.next
return self.head
class DoublyLinkedList():
def __init__(self):
"""
Create a new doubly linked list.
Takes O(1) time.
"""
self.head = None
def __repr__(self):
"""
Return a string representation of the list.
Takes O(n) time.
"""
nodes = []
curr = self.head
while curr:
nodes.append(repr(curr))
curr = curr.next
return '[' + ', '.join(nodes) + ']'
def prepend(self, data):
"""
Insert a new element at the beginning of the list.
Takes O(1) time.
"""
new_head = DListNode(data=data, next=self.head)
if self.head:
self.head.prev = new_head
self.head = new_head
def append(self, data):
"""
Insert a new element at the end of the list.
Takes O(n) time.
"""
if not self.head:
self.head = DListNode(data=data)
return
curr = self.head
while curr.next:
curr = curr.next
curr.next = DListNode(data=data, prev=curr)
def find(self, key):
"""
Search for the first element with `data` matching
`key`. Return the element or `None` if not found.
Takes O(n) time.
"""
curr = self.head
while curr and curr.data != key:
curr = curr.next
return curr # Will be None if not found
def remove_elem(self, node):
"""
Unlink an element from the list.
Takes O(1) time.
"""
if node.prev:
node.prev.next = node.next
if node.next:
node.next.prev = node.prev
if node is self.head:
self.head = node.next
node.prev = None
node.next = None
def remove(self, key):
"""
Remove the first occurrence of `key` in the list.
Takes O(n) time.
"""
elem = self.find(key)
if not elem:
return
self.remove_elem(elem)
def reverse(self):
"""
Reverse the list in-place.
Takes O(n) time.
"""
curr = self.head
prev_node = None
while curr:
prev_node = curr.prev
curr.prev = curr.next
curr.next = prev_node
curr = curr.prev
self.head = prev_node.prev
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment