Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linked List CS Fun Project #65

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 155 additions & 16 deletions linked_list/linked_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,63 +13,144 @@ def __init__(self):

# returns the value in the first node
# returns None if the list is empty
# Time Complexity: ?
# Space Complexity: ?
# Time Complexity: 0(1)
# Space Complexity: 0(n)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be O(1), because we aren't creating any new data inside the function that is dependent on the size of the link

def get_first(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pass
if self.head == None:
return None
#The other scenario would mean there is a value in the first node or the 1st node exists.
else:
return self.head.value



# method to add a new node with the specific data value in the linked list
# insert the new node at the beginning of the linked list
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 29 to 30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def add_first(self, value):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pass
if self.head == None:
new_node = Node(value=value, next_node=None)
self.head= new_node
else:
new_node = Node(value=value, next_node=self.head)
self.head = new_node


# method to find if the linked list contains a node with specified value
# returns true if found, false otherwise
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 42 to 43

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def search(self, value):
pass
if self.head == None:
return False
else:
current = self.head
while current != None:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! one way to shorten this is:

Suggested change
while current != None:
while current:

if current.value == value:
return True
else:
current = current.next
return False


# method that returns the length of the singly linked list
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 58 to 59

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def length(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pass
if self.head == None:
return 0
else:
counter = 0
current = self.head
while current != None:
counter += 1
current = current.next
return counter


# method that returns the value at a given index in the linked list
# index count starts at 0
# returns None if there are fewer nodes in the linked list than the index value
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 75 to 76

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def get_at_index(self, index):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pass
if self.head == None:
return None
else:
counter = 0
current = self.head
while current != None:
if counter == index:
return current.value
else:
counter += 1
current = current.next
return None

# method that returns the value of the last node in the linked list
# returns None if the linked list is empty
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 93 to 94

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def get_last(self):
pass
if self.head == None:
return None
else:
current = self.head
while current != None:
if current.next == None:
return current.value
else:
current = current.next
Comment on lines +100 to +104

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! another way we could do this is change the while statement to while current.next, then once the while loops ends, the current variable will hold the last node

Suggested change
while current != None:
if current.next == None:
return current.value
else:
current = current.next
while current.next:
current = current.next
return current.value


# method that inserts a given value as a new last node in the linked list
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 107 to 108

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def add_last(self, value):
pass
new_node = Node(value, next_node=None)
if self.head == None:
self.head = new_node
else:
current = self.head
while current != None:
if current.next == None:
new_node = Node(value, next_node=None)
current.next = new_node
current = current.next
return
else:
current = current.next
Comment on lines +115 to +122

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like above, we could change up the while statement in order to use less lines of code:

Suggested change
while current != None:
if current.next == None:
new_node = Node(value, next_node=None)
current.next = new_node
current = current.next
return
else:
current = current.next
while current.next:
current = current.next
current.next = Node(value, next_node=None)


# method to return the max value in the linked list
# returns the data value and not the node
def find_max(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pass
if self.head == None:
return None
else:
final_max = self.head.value
current = self.head.next
while current != None:
if current.value > final_max:
final_max = current.value
current = current.next
return final_max

# method to delete the first node found with specified value
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 139 to 140

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def delete(self, value):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pass
if self.head == None:
return None
elif self.head.value == value:
self.head = self.head.next
else:
current = self.head
while current.next != None:
if current.next.value == value:
current.next = current.next.next
return
else:
current = current.next

# method to print all the values in the linked list
# Time Complexity: ?
Expand All @@ -89,29 +170,87 @@ def visit(self):
# Time Complexity: ?
# Space Complexity: ?
Comment on lines 170 to 171

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think the space and time complexity of this is? Is the time complexity dependent on the length of the linked list? Is there any new variables being created that grow larger depending upon the input?

def reverse(self):
pass
if self.head == None:
return
elif self.head.next == None:
return
else:
current = self.head
reversed_link = None
while current.next != None:
if not reversed_link:
next_node = current.next
current.next = None
reversed_link = current
current = next_node
else:
Comment on lines +181 to +186

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I don't think we need this first if statement if we change the while loop to while current != None. I think starting reversed_link as None like you did and then going into the else statement will work

next_node = current.next
current.next = reversed_link
reversed_link = current
current = next_node
current.next = reversed_link
reversed_link = current
Comment on lines +191 to +192

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can get rid of these two lines if we change the while loop

self.head = reversed_link
return self

## Advanced/ Exercises
# returns the value at the middle element in the singly linked list
# Time Complexity: ?
# Space Complexity: ?
def find_middle_value(self):
pass
if self.head == None:
return None
elif self.head.next == None:
return self.head.value
else:
one_step_current = self.head
two_step_current = self.head
while two_step_current != None and two_step_current.next != None:
one_step_current = one_step_current.next
two_step_current = two_step_current.next.next
return one_step_current.value

# find the nth node from the end and return its value
# assume indexing starts at 0 while counting to n
# Time Complexity: ?
# Space Complexity: ?
def find_nth_from_end(self, n):
pass
if self.head == None:
return None
else:
one_step_current = self.head
n_step_current = self.head
counter = 0
while n_step_current.next != None:
if counter < n:
n_step_current = n_step_current.next
counter += 1
else:
n_step_current = n_step_current.next
one_step_current = one_step_current.next
if counter < n:
return None
else:
return one_step_current.value

# checks if the linked list has a cycle. A cycle exists if any node in the
# linked list links to a node already visited.
# returns true if a cycle is found, false otherwise.
# Time Complexity: ?
# Space Complexity: ?
def has_cycle(self):
pass
if self.head == None:
return False
else:
node_set = set()
current = self.head
while current != None:
if current not in node_set:
node_set.add(current)
current = current.next
else:
return True
return False

# Helper method for tests
# Creates a cycle in the linked list for testing purposes
Expand All @@ -125,4 +264,4 @@ def create_cycle(self):
while current.next != None:
current = current.next

current.next = self.head # make the last node link to first node
current.next = self.head # make the last node link to first node