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
23 changes: 23 additions & 0 deletions problem28.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
result = [0]*len(nums)
#take the running sum of products. For an integer nums[i] take left running sum and then find its right running sum and multiply them both together.

#taking the left side running sum
rp = 1

for i,num in enumerate(nums):
result[i] = rp
rp = num*rp

#taking the right side running sum
rp = 1

for i in range (len(nums)-1, -1, -1):
result[i] *= rp
rp *= nums[i]

return result

# Time Complexity: O(N)
# Space Complexity: O(1) if you don't consider the output array, else O(N)
104 changes: 104 additions & 0 deletions problem29.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#my code initial thought process:

from typing import List


class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
result = []
m = len(mat) #rows
n = len(mat[0]) #cols

if m == 1 and n == 1:
return [mat[0][0]]

top = True

i = 0
j = 0

while top and i >= 0 and i < m and j >=0 and j<n:

#upwards top and right boundary
while i >=0 and j < n:
result.append(mat[i][j])
i = i-1
j = j+1

if j > n-1:
i += 2
j = j-1
else:
i = 0

top = False

#downwards left and bottom
while (j >= 0 and i < m) and not top:
result.append(mat[i][j])
i = i+1
j = j-1

if i > m-1:
i = i-1
j = j+2

else:
j = 0
top = True
return result


# up-right diagonals don’t always end by hitting the top wall.
# Sometimes they end by hitting the right wall (j == n). In that case, resetting i = 0 is wrong.
# Down-left diagonals sometimes end at the left wall (j == -1) and sometimes at the bottom wall (i == m), and each needs a different fix.

#more clean code:

class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
result = []
m = len(mat) #rows
n = len(mat[0]) #cols

row = 0
col = 0
dir = True

#find all cases where we need to reverse directions

while row < m and col < n:
result.append(mat[row][col]) #always add the first element

if dir: #for upward traversals boundaries are roof and right so when we hit boundaries
if row == 0 and col != n-1: #roof boundary is reached as roof boundary is row = zero
col += 1
dir = False
elif col == n-1: #right boundary is reached as right boundary = col n-1 and the corner case is also reached
row += 1
dir = False
else:
row -= 1 #general cases in upward dir when we are not hitting boundaries
col += 1

else: #for downward traversal left and bottom are boundaries
if row == m-1: #hit bottom boundary and corner case is handled here
col += 1
dir = True

elif col == 0 and row != m-1: #hit left boundary or the corner case
row += 1
dir = True
else:
#generally
col -= 1
row += 1
return result

#we need to handle the intersection of two boundaries or the corner cases here as it can also go OOB
#when to decide i have to flip the directions
#in which direction we have to flip
#if we are on (0,0) how to decide which index to go to.

# Time Complexity : O(m*n)
# Space Complexity: O(1) (O(m*n) if u want to consider result also)
97 changes: 97 additions & 0 deletions problem30.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from typing import List


class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:

#top bottom left and right defines the boundaries and after each spiral, these boundaries
#changes

m = len(matrix) #rows
n = len(matrix[0]) #cols
result = []

top, left, right, bottom = 0, 0, n - 1, m - 1

while top <= bottom and left <= right:

for i in range(left, right+1):
result.append(matrix[top][i])

top += 1

for i in range(top, bottom+1): #if top > bottom then this for loop won't run
result.append(matrix[i][right])

right -= 1

if top <= bottom: #if base condition var gets mutated always check them again
for i in range(right, left-1, -1):
result.append(matrix[bottom][i])

bottom -= 1

if left <= right:
for i in range(bottom, top-1, -1):
result.append(matrix[i][left])
left += 1


return result

# Time Complexity: O(m*n)
# Space Complexity: O(1)

class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:

#top bottom left and right defines the boundaries and after each spiral, these boundaries
#changes

m = len(matrix) #rows
n = len(matrix[0]) #cols
result = []

top, left, right, bottom = 0, 0, n - 1, m - 1

def helper(matrix, top, left, right, bottom, result):

if top > bottom or left > right: #That’s the key reason recursion depth is min(m, n). Stop when either dimensionality is
#exhausted
return

for i in range(left, right+1):
result.append(matrix[top][i])

top += 1

for i in range(top, bottom+1):
result.append(matrix[i][right])
right -= 1

if top <= bottom:
for i in range(right, left-1, -1):
result.append(matrix[bottom][i])

bottom -= 1

if left <= right:
for i in range(bottom, top-1, -1):
result.append(matrix[i][left])

left += 1

helper(matrix, top, left, right, bottom,result)

helper (matrix, top, left, right, bottom, result)

return result

# Recursive solution:

# Time Complexity: O(m*n)
# Space Complexity: recursive stack depends no. of spirals
# O(min(m, n))
# because each recursive call removes one spiral layer, and the number of layers is bounded by the smaller matrix dimension.
# After one recursive call, the matrix shrinks like this (m-2) rows*(n-2) cols. Each call reduces both dimensions.
#ceil(min(m, n) / 2) = 3, basically whichever exhausts first either row or col.