From e7d6a9aded45d0966b1f995b824fa51c8f3d1196 Mon Sep 17 00:00:00 2001 From: shaurya22c Date: Mon, 27 Jul 2026 21:50:50 -0400 Subject: [PATCH] Completed PreCourse - 1 --- Exercise_1.py | 54 ++++++++++++++++++++++------ Exercise_2.py | 70 ++++++++++++++++++++++++++++++++++++ Exercise_3.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 211 insertions(+), 11 deletions(-) diff --git a/Exercise_1.py b/Exercise_1.py index 532833f5d..d96b8fcc6 100644 --- a/Exercise_1.py +++ b/Exercise_1.py @@ -1,24 +1,58 @@ +""" +Time complexity: +O(1) for push, pop, peek, isEmpty, size. +O(n) for show() + +Space complexity: +O(n) -> n is the number of elements in array +""" + class myStack: - #Please read sample.java file before starting. - #Kindly include Time and Space complexity at top of each file - def __init__(self): + + def __init__(self, cap): + self.arr = [0]*cap + self.capacity = cap + self.top = -1 def isEmpty(self): + return self.top == -1 def push(self, item): + # check for stack overflow + if self.top == self.capacity - 1: + print("Stack overflow") + return + self.top += 1 + self.arr[self.top] = item def pop(self): - + # check for stack underflow + if self.top == -1: + print("Stack underflow") + return + self.top -= 1 + return self.arr[self.top] def peek(self): + if self.isEmpty(): + print("Stack is empty") + return + return self.arr[self.top] def size(self): + return self.top + 1 def show(self): - + print("Showing stack elements:") + for i in range(self.top + 1): + print(self.arr[i]) + +def main(): + s = myStack(5) + s.push('1') + s.push('2') + print(s.pop()) + s.show() -s = myStack() -s.push('1') -s.push('2') -print(s.pop()) -print(s.show()) +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Exercise_2.py b/Exercise_2.py index b11492215..02096299d 100644 --- a/Exercise_2.py +++ b/Exercise_2.py @@ -1,3 +1,20 @@ +""" +Implement Stack using Linked List + +Time Complexity: +push() - O(1) +pop() - O(1) + +Space Complexity: +O(n) - where n is the number of elements in stack + +Notes: + +-> while working with stack, we use top as pointer variable. +-> check conditions related to top. +-> push() - add new node to the top +-> pop() - remove node (if available) from top +""" class Node: def __init__(self, data): @@ -6,10 +23,61 @@ def __init__(self, data): class Stack: def __init__(self): + self.top = None def push(self, data): + # create new node to push + new_node = Node(data) + + # check if stack is empty + if self.top is None: + # assign new node to top + self.top = new_node + self.top.next = None + + else: + # create a link betweem new_node and current top + new_node.next = self.top + # make new_node as top - so top is updated now + self.top = new_node def pop(self): + + # Stack is empty + if self.top is None: + return + + # If stack has only one element + elif self.top.next is None: + popped_value = self.top.data + # top becomes None + self.top = None + return popped_value + # Stack has more than one element + else: + # create temp variable + temp = self.top + popped_value = self.top.data + + # update top + self.top = temp.next + + # delete element + temp = None + return popped_value + + def display(self): + # check if stack is empty + if self.top is None: + print("Stack is empty") + return + + temp = self.top + print("Stack elements:") + while temp: + print(temp.data) + temp = temp.next + return a_stack = Stack() while True: @@ -30,3 +98,5 @@ def pop(self): print('Popped value: ', int(popped)) elif operation == 'quit': break + elif operation == 'display': + a_stack.display() \ No newline at end of file diff --git a/Exercise_3.py b/Exercise_3.py index a5d466b59..6d43b0e74 100644 --- a/Exercise_3.py +++ b/Exercise_3.py @@ -1,8 +1,16 @@ +""" +Time Complexity: + +Space Complexity: +""" + class ListNode: """ A node in a singly-linked list. """ def __init__(self, data=None, next=None): + self.data = data + self.next = next class SinglyLinkedList: def __init__(self): @@ -12,11 +20,25 @@ def __init__(self): """ self.head = None - def append(self, data): + def append(self, node: ListNode): """ Insert a new element at the end of the list. Takes O(n) time. """ + + # If linkedlist is empty, the new node just becomes the head + if self.head is None: + self.head = node + return + + temp = self.head + + # move to the last Node + while temp.next: + temp = temp.next + + temp.next = node + def find(self, key): """ @@ -24,9 +46,83 @@ def find(self, key): `key`. Return the element or `None` if not found. Takes O(n) time. """ + + # If linkedlist is empty + if self.head is None: + return None + + temp = self.head + + while temp.data != key: + temp = temp.next + + if temp is None: + return None + + return temp def remove(self, key): """ Remove the first occurrence of `key` in the list. Takes O(n) time. """ + + # If linkedlist is empty, there is nothing to remove + if self.head is None: + return + + # Special case: the key is in the head node itself + if self.head.data == key: + self.head = self.head.next + return + + prev = self.head + temp = self.head.next + + # Traverse until key is found, moving prev and temp together + while temp is not None and temp.data != key: + prev = temp + temp = temp.next + + # Key was not found anywhere in the list + if temp is None: + return + + # Unlink temp by pointing prev past it + prev.next = temp.next + temp.next = None + + def display(self): + """ + Print the contents of the list from head to tail. + Takes O(n) time. + """ + current = self.head + values = [] + + while current is not None: + values.append(str(current.data)) + current = current.next + + print(" -> ".join(values)) + + +def main(): + n1 = ListNode(10) + l = SinglyLinkedList() + l.head = n1 + + n2 = ListNode(20) + n1.next = n2 + + n3 = ListNode(30) + n2.next = n3 + + n4 = ListNode(40) + l.append(n4) + l.remove(30) + + l.display() + +if __name__ == "__main__": + main()