Skip to content

Commit

Permalink
Merge pull request #811 from dusunax/main
Browse files Browse the repository at this point in the history
[SunaDu] Week 4
  • Loading branch information
dusunax authored Jan 4, 2025
2 parents 41a2c03 + cb5c505 commit 33558fa
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
49 changes: 49 additions & 0 deletions coin-change/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'''
# 322. Coin Change
use a queue for BFS & iterate through the coins and check the amount is down to 0.
use a set to the visited check.
## Time and Space Complexity
```
TC: O(n * Amount)
SC: O(Amount)
```
#### TC is O(n * Amount):
- sorting the coins = O(n log n)
- reversing the coins = O(n)
- iterating through the queue = O(Amount)
- iterating through the coins and check the remaining amount is down to 0 = O(n)
#### SC is O(Amount):
- using a queue to store (the remaining amount, the count of coins) tuple = O(Amount)
- using a set to store the visited check = O(Amount)
'''
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
if amount == 0:
return 0
if len(coins) == 1 and coins[0] == amount:
return 1

coins.sort() # TC: O(n log n)
coins.reverse() # TC: O(n)

queue = deque([(amount, 0)]) # SC: O(Amount)
visited = set() # SC: O(Amount)

while queue: # TC: O(Amount)
remain, count = queue.popleft()

for coin in coins: # TC: O(n)
next_remain = remain - coin

if next_remain == 0:
return count + 1
if next_remain > 0 and next_remain not in visited:
queue.append((next_remain, count + 1))
visited.add(next_remain)

return -1
77 changes: 77 additions & 0 deletions merge-two-sorted-lists/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'''
# 21. Merge Two Sorted Lists
A. iterative approach: use a two pointers to merge the two lists.
B. recursive approach: use recursion to merge the two lists.
## Time and Space Complexity
### A. Iterative Approach
```
TC: O(n + m)
SC: O(1)
```
#### TC is O(n + m):
- iterating through the two lists just once for merge two sorted lists. = O(n + m)
#### SC is O(1):
- temp node is used to store the result. = O(1)
### B. Recursive Approach
```
TC: O(n + m)
SC: O(n + m)
```
#### TC is O(n + m):
- iterating through the two lists just once for merge two sorted lists. = O(n + m)
#### SC is O(n + m):
- because of the recursive call stack. = O(n + m)
'''
class Solution:
'''
A. Iterative Approach
- use a temp node to store the result.
- use a current node to iterate through the two lists.
'''
def mergeTwoListsIterative(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
temp = ListNode(-1)
current = temp

while list1 is not None and list2 is not None:
if list1.val < list2.val:
current.next = list1
list1 = list1.next
else:
current.next = list2
list2 = list2.next
current = current.next

if list1 is not None:
current.next = list1
elif list2 is not None:
current.next = list2

return temp.next

'''
B. Recursive Approach
- use recursion to merge the two lists.
'''
def mergeTwoListsRecursive(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if list1 is None:
return list2
elif list2 is None:
return list1

if list1.val < list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list1, list2.next)
return list2
63 changes: 63 additions & 0 deletions missing-number/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'''
# 268. Missing Number
A. iterative approach: sort the array and find the missing number.
B. XOR approach: use XOR to find the missing number.
- a ^ a = 0, a ^ 0 = a
## Time and Space Complexity
### A. Iterative Approach
```
TC: O(n log n)
SC: O(1)
```
#### TC is O(n):
- sorting the array. = O(n log n)
- iterating through the array just once to find the missing number. = O(n)
#### SC is O(1):
- no extra space is used. = O(1)
### B. XOR Approach
```
TC: O(n)
SC: O(1)
```
#### TC is O(n):
- iterating through the array just once to find the missing number. = O(n)
#### SC is O(1):
- no extra space is used. = O(1)
'''
class Solution:
'''
A. Iterative Approach
'''
def missingNumberIterative(self, nums: List[int]) -> int:
nums.sort()
n = len(nums)

for i in range(n):
if nums[i] != i:
return i
return n

'''
B. XOR Approach
'''
def missingNumberXOR(self, nums: List[int]) -> int:
n = len(nums)
xor_nums = 0

for i in range(n + 1):
if i < n:
xor_nums ^= nums[i]
xor_nums ^= i

return xor_nums
78 changes: 78 additions & 0 deletions palindromic-substrings/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'''
# 647. Palindromic Substrings
A. use dynamic programming table to store the palindrome status.
B. use two pointers to expand around the center.
## Time and Space Complexity
### A. Dynamic Programming Table
```
TC: O(n^2)
SC: O(n^2)
```
#### TC is O(n^2):
- filling DP table by iterating through all substrings.
- each cell (i, j) checks if a substring is a palindrome & counting the cases = O(n^2)
#### SC is O(n^2):
- storing the n x n dp table. = O(n^2)
### B. Expand Around Center
```
TC: O(n^2)
SC: O(1)
```
#### TC is O(n^2):
- for each char, expand outwards to check for palindromes. = O(n^2)
#### SC is O(1):
- no additional data structures are used. `count` is a single integer. = O(1)
'''
class Solution:
def countSubstringsDPTable(self, s: str) -> int:
'''
A. Dynamic Programming Table
'''
n = len(s)
dp = [[False] * n for _ in range(n)] # List comprehension. = SC: O(n^2)
count = 0

for i in range(n): # TC: O(n)
dp[i][i] = True
count += 1

for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
count += 1

for s_len in range(3, n + 1): # TC: O(n)
for i in range(n - s_len + 1): # TC: O(n)
j = i + s_len - 1

if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
count += 1

return count
def countSubstrings(self, s: str) -> int:
'''
B. Expand Around Center
'''
count = 0

def expand(left, right):
nonlocal count
while left >= 0 and right < len(s) and s[left] == s[right]: # TC: O(n)
count += 1
left -= 1
right += 1

for i in range(len(s)): # TC: O(n)
expand(i, i)
expand(i, i + 1)

return count
52 changes: 52 additions & 0 deletions word-search/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'''
# 79. Word Search
use backtracking(DFS) to search for the word in the board.
## Time and Space Complexity
```
TC: O(n * m * 4^L)
SC: O(L)
```
#### TC is O(n * m * 4^L):
- n is the number of rows in the board.
- m is the number of columns in the board.
- L is the length of the word.
- 4^L is the number of directions we can go at each step. (explores 4 branches recursively)
#### SC is O(L):
- modifying the board in-place to mark visited cells. = O(L)
'''
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
rows = len(board)
cols = len(board[0])

def backtracking(i, j, word_index): # TC: O(4^L), SC: O(L)
if word_index == len(word):
return True

if i < 0 or i >= rows or j < 0 or j >= cols or board[i][j] != word[word_index]:
return False

temp = board[i][j]
board[i][j] = "."

found = (
backtracking(i + 1, j, word_index + 1) or
backtracking(i - 1, j, word_index + 1) or
backtracking(i, j + 1, word_index + 1) or
backtracking(i, j - 1, word_index + 1)
)
board[i][j] = temp

return found

for row in range(rows): # TC: O(n * m)
for col in range(cols):
if backtracking(row, col, 0):
return True

return False

0 comments on commit 33558fa

Please sign in to comment.