Objected Oriented Programming

Object-Oriented Programming (OOP) is a programming paradigm centered around objects — which bundle data (attributes) and behavior (methods) together.

Instead of writing code as a series of steps (procedural programming), OOP organizes code into classes that create objects — like blueprints and the actual items built from them.

ConceptDescriptionExample (Python)

Class A blueprint for creating objects class Car:
Object An instance of a class my_car = Car()
Encapsulation Hiding internal data using methods and attributes Private attributes with getters/setters
Abstraction Showing only essential details, hiding complexity A Car.start() method hides engine logic
Inheritance One class can derive from another, reusing code class ElectricCar(Car):
Polymorphism Methods behave differently based on the object Both Car and Boat implement move() differently

 

  LRU Cache

Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.

Implement the LRUCache class:

  LRUCache(int capacity) Initialize the LRU cache with positive size capacity.

  int get(int key) Return the value of the key if the key exists, otherwise return -1.

  void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the     cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.

The functions get and put must each run in O(1) average time complexity.

 

class Node:
    def __init__(self, key = None, val = None, prev = None, next = None):
        self.val = val
        self.prev = prev
        self.next = next
        self.key = key
class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.map = {}
        self.head = Node()
        self.tail = Node()
        self.head.next = self.tail
        self.tail.prev = self.head


    def get(self, key: int) -> int:
        if key in self.map:
            self.delNode(key)
            self.addLast(key)
            return self.map[key].val
        else:
            return -1
        

    def put(self, key: int, value: int) -> None:
        if key not in self.map:
            if len(self.map) < self.capacity:                 
                self.map[key] = Node(key = key, val = value)
                self.addLast(key)
            else:
                self.map[key] = Node(key = key, val = value)
                delKey = self.head.next.key
                self.delNode(delKey)
                self.addLast(key)
                del self.map[delKey]
        else:
            self.map[key].val = value
            self.delNode(key)
            self.addLast(key)
    
  
  def addLast(self, key):
        prev = self.tail.prev
        cur = self.map[key]
        prev.next = cur
        cur.prev = prev
        self.tail.prev = cur
        cur.next = self.tail
    
    def delNode(self, key):
        cur = self.map[key]
        prev = cur.prev
        next = cur.next
        prev.next = next
        next.prev = prev
    
  

Min Stack

 

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

Implement the MinStack class:

- MinStack() initializes the stack object

- void push(int val) pushes the element val onto the stack.

- void pop() removes the element on the top of the stack.int top() gets the top element of the stack.

- int getMin() retrieves the minimum element in the stack.

You must implement a solution with O(1) time complexity for each function.

 

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.arr = []
        self.heap = []
        self.remove = set()
        self.id = 0

    def push(self, val: int) -> None:
        self.arr.append((val, self.id))
        heapq.heappush(self.heap, (val, self.id))
        self.id += 1
        
    def pop(self) -> None:
        last = self.arr.pop()
        self.remove.add(last[1])
        self.clean()
        return last[0]

    def top(self) -> int:
        last = self.arr[-1]
        return last[0]

    def getMin(self) -> int:
        return self.heap[0][0]
    
    def clean(self):
        while self.heap and self.heap[0][1] in self.remove:
            v, index = heapq.heappop(self.heap)
            self.remove.remove(index)