-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #811 from dusunax/main
[SunaDu] Week 4
- Loading branch information
Showing
5 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |