Skip to content
Open
Show file tree
Hide file tree
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
71 changes: 71 additions & 0 deletions Problem1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Problem 1: Rotting Oranges(https://leetcode.com/problems/rotting-oranges)
# Time Complexity: O(m*n)
# Space Complexity: O(m*n)
# Approach:
# First we scan the whole grid once to collect all rotten oranges into a queue and count how many fresh oranges exist.
# Then we do BFS minute by minute. In each minute we only process the oranges that were rotten at the start of that minute and rot their fresh neighbors, adding them to the queue for the next minute.
# If the fresh count reaches zero we return the current time right away. If the queue empties out before that happens, some oranges were unreachable, so we return minus one.

class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:

# these are the four possible moves from any cell, up down right left, used to check all four neighbors without writing four separate conditions
self.directions = [[-1,0],[1,0],[0,1],[0,-1]]


self.m = len(grid) # m is the number of rows in the grid
self.n = len(grid[0]) # n is the number of columns in the grid

queue = [] # queue will hold the positions of rotten oranges that still need to spread their rot
fresh = 0 # fresh keeps a running count of how many fresh oranges are still left in the grid

# this loop goes through every single cell in the grid exactly once
for i in range(self.m):
for j in range(self.n):
# if this cell is rotten, we add its position to the queue since it will spread rot from here
if grid[i][j] == 2:
queue.append((i, j))
# if this cell is fresh, we simply increase our fresh counter
if grid[i][j] == 1:
fresh += 1

# time tracks how many minutes have passed
time = 0
# if there were no fresh oranges to begin with, no rotting needs to happen, so we return zero right away
if fresh == 0:
return time

# this loop keeps running as long as there are rotten oranges waiting to spread their rot
while queue:
# size captures exactly how many rotten oranges are in the queue at the start of this minute
# this is important because it tells us where one minute ends and the next minute begins
size = len(queue)
# one full minute is about to pass for all these oranges together, so we increase time now
time += 1

# we only loop size times so we only process oranges that belong to this exact minute, not oranges added during this same minute
for i in range(size):
# we take the orange that has been waiting the longest, since we want first in first out order
current = queue.pop(0)

# we check all four neighbors of this rotten orange one by one
for dir in self.directions:
# row is the neighbor's row, found by adding the row change to the current row
row = current[0] + dir[0]
# column is the neighbor's column, found by adding the column change to the current column
column = current[1] + dir[1]

# we only continue if the neighbor is inside the grid boundaries and the neighbor is currently a fresh orange
if row >= 0 and column >= 0 and row < self.m and column < self.n and grid[row][column] == 1:
# we mark this neighbor as rotten directly on the grid so it is never processed again
grid[row][column] = 2
# we add this newly rotten orange to the queue so it can spread rot in the next minute
queue.append((row, column))
# one less fresh orange remains now
fresh -= 1
# if there are no fresh oranges left at all, we are done, so we return the current time immediately
if fresh == 0:
return time

# if we reach here, the queue became empty but some fresh oranges never got rotten, meaning they were unreachable
return -1
48 changes: 48 additions & 0 deletions Problem2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Problem 2: Employee Impotance(https://leetcode.com/problems/employee-importance/)
#Time Complexity: O(N), where N is the number of employees, because we visit each employee exactly once during the map building step and exactly once during the DFS step.
#Space Complexity: O(N), because we store every employee in the map and in the worst case the recursion stack can go as deep as N if the hierarchy is a long chain.
#Approach: We first build a map that connects each employee id to their actual employee object, since the subordinates list only gives us ids and not the full object. Then we use DFS starting from the given id, adding up the importance value of every employee we visit, including the starting employee and all their direct and indirect subordinates. The recursion naturally keeps going deeper until there are no more subordinates left to explore.


# Definition for Employee.
class Employee:
def __init__(self, id: int, importance: int, subordinates: List[int]):
self.id = id
self.importance = importance
self.subordinates = subordinates


class Solution:
def getImportance(self, employees: List['Employee'], id: int) -> int:
# this map will let us jump from an employee id straight to the actual employee object
# we need this because subordinates are stored as plain ids, not as objects we can use directly
self.map = {}

# we loop through every employee once and store them in the map using their id as the key
# this way later on we can look up any employee in constant time instead of searching the whole list again
for emp in employees:
self.map[emp.id] = emp

# this will hold the running total of importance as we visit employees
self.result = 0

# we start the depth first search from the given id
# this call will handle adding importance for this employee and all their subordinates
self.dfs(id)
return self.result

def dfs(self, id):
# we look up the actual employee object for this id using our map
# this is fast because the map gives us direct access instead of searching
emp = self.map[id]

# we add this employee's own importance value to the running total
# this happens for the starting employee and every subordinate we visit along the way
self.result += emp.importance

# now we go through each subordinate id that belongs to this employee
for subid in emp.subordinates:
# we call dfs again on this subordinate
# this is what lets us reach not just direct subordinates but also their subordinates and so on
# the recursion keeps going deeper until it reaches an employee with no subordinates left
self.dfs(subid)