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
22 changes: 22 additions & 0 deletions Problem1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Problem1 (https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/)
# TC = O(n)
# SC = O(1)
#Did this code successfully run on Leetcode : Yes
# Use the array itself to mark which numbers exist: for each value seen,
# flip the number at its corresponding index (value-1) negative,
# then any index still positive after that means its corresponding number (index+1) was never found.

class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
n = len(nums)
result = []
for i in range(n): # marking pass: go through every index in the array
index = abs(nums[i]) - 1 # convert this value into the index it "belongs to" (use abs() since it may already be flipped negative)
if nums[index] > 0: # check if that target index hasn't been marked yet
nums[index] *= -1 # flip it negative to record "this number exists"

for i in range(n): # checking pass: go through every index one more time
if nums[i] > 0: # still positive means nothing ever pointed to this index
result.append(i + 1) # convert index back to value and mark it missing

return result
40 changes: 40 additions & 0 deletions Problem2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#https://www.geeksforgeeks.org/dsa/maximum-and-minimum-in-an-array/
# TC = O(n)
# SC = O(1)
# Process the array two elements at a time: compare each pair against each other first,
# then only check the smaller one against mini and the larger one against maxi,
# cutting comparisons from 4 to 3 per pair.

def find_min_max(arr):
n = len(arr)
if n % 2 == 1: # check if array length is odd
mini = maxi = arr[0] # seed both mini and maxi with the first element
i = 1 # start pairing loop from index 1, since index 0 is already used
else:
if arr[0] < arr[1]: # compare the first two elements to seed mini/maxi
mini = arr[0] # arr[0] is smaller, so it becomes the initial min
maxi = arr[1] # arr[1] is larger, so it becomes the initial max
else:
mini = arr[1] # arr[1] is smaller, so it becomes the initial min
maxi = arr[0] # arr[0] is larger, so it becomes the initial max
i = 2 # start pairing loop from index 2, since indices 0 and 1 are already used

while i < n - 1: # loop while a full pair (i and i+1) still exists in bounds
if arr[i] < arr[i + 1]: # compare the pair against each other
mini = min(arr[i], mini) # arr[i] is the smaller one, check it against current min
maxi = max(arr[i + 1], maxi) # arr[i+1] is the larger one, check it against current max
else:
mini = min(arr[i + 1], mini)
maxi = max(arr[i], maxi)
i += 2 # move forward by 2 to process the next pair

return [mini, maxi]


def main():
arr = [3, 5, 4, 1, 9]
result = find_min_max(arr)
print(result[0], result[1])

if __name__ == "__main__":
main()
53 changes: 53 additions & 0 deletions Problem3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#https://leetcode.com/problems/game-of-life/
# Time Complexity: O(m * n) -> we visit every cell once in pass 1 (each visit checks 8 neighbors, a constant) then every cell once again in pass 2, so total work scales with grid size
# Space Complexity: O(1)
# Use 2 extra encoded states (2 = live->dying, 3 = dead->being born) so we can read the ORIGINAL generation's values while deciding the NEXT generation, without needing a second grid.
# Pass 1 scans every cell, counts live neighbors using getCount(), and marks transitions (2 or 3) based on the 4 Game of Life rules, without overwriting the original 0/1 meaning yet.
# Pass 2 converts the encoded markers back to real 0/1 values, giving the final next-generation board.
# list of all 8 neighbor offsets (dx = row shift, dy = column shift) around any cell excludes (0,0) since that would be the cell itself, not a neighbor



class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
directions = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)]

m = len(board)
n = len(board[0])
# helper function: counts how many of cell (i, j)'s neighbors are CURRENTLY alive
# i = row index of the cell we're checking neighbors for
# j = column index of the cell we're checking neighbors for
def getCount(i, j):
count = 0 # running tally of live neighbors found so far, starts at 0
for dx, dy in directions: # loop through all 8 direction offsets one at a time
row, column = i + dx, j + dy # row, column = the neighbor's actual position on the board
if 0 <= row < m and 0 <= column < n: # boundary check: skip if neighbor would be off the grid
# a value of 1 = currently alive, 2 = currently alive but marked to die next round
# both count as "alive right now", which is what we care about for this generation
if board[row][column] == 1 or board[row][column] == 2:
count += 1 # found a live neighbor, increment the tally
return count
# PASS 1: decide every cell's fate based on the ORIGINAL board values, but don't apply changes yet
for i in range(m):
for j in range(n):
finalcount = getCount(i, j) # finalcount = number of live neighbors for cell (i, j)

# Rule 4: cell is currently dead AND has exactly 3 live neighbors
if board[i][j] == 0 and finalcount == 3:
board[i][j] = 3

# Rules 1 & 3 (under/over-population): cell is currently alive AND has too few/too many neighbors
elif board[i][j] == 1 and (finalcount < 2 or finalcount > 3):
board[i][j] = 2
# NOTE: Rule 2 (2 or 3 neighbors -> stays alive) needs no code; the cell just remains 1 untouched

# PASS 2: convert all placeholder markers into their real final 0/1 values
for i in range(m):
for j in range(n):
if board[i][j] == 2:
board[i][j] = 0
elif board[i][j] == 3:
board[i][j] = 1