diff --git a/coin-change/ayosecu.py b/coin-change/ayosecu.py new file mode 100644 index 000000000..2c9c37132 --- /dev/null +++ b/coin-change/ayosecu.py @@ -0,0 +1,30 @@ +from typing import List + +class Solution: + """ + - Time Complexity: O(CA), C = len(coins), A = amount + - Space Complexity: O(A), A = amount + """ + def coinChange(self, coins: List[int], amount: int) -> int: + # DP + dp = [float("inf")] * (amount + 1) + dp[0] = 0 # 0 amount needs 0 coin + + for coin in coins: + for i in range(coin, amount + 1): + # dp[i] => not use current coin + # dp[i - coin] + 1 => use current coin + dp[i] = min(dp[i], dp[i - coin] + 1) + + return dp[amount] if dp[amount] != float("inf") else -1 + +tc = [ + ([1,2,5], 11, 3), + ([2], 3, -1), + ([1], 0, 0) +] + +for i, (coins, amount, e) in enumerate(tc, 1): + sol = Solution() + r = sol.coinChange(coins, amount) + print(f"TC {i} is Passed!" if r == e else f"TC {i} is Failed! - Expected: {e}, Result: {r}") diff --git a/find-minimum-in-rotated-sorted-array/ayosecu.py b/find-minimum-in-rotated-sorted-array/ayosecu.py new file mode 100644 index 000000000..063228b7a --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/ayosecu.py @@ -0,0 +1,32 @@ +from typing import List + +class Solution: + """ + - Time Complexity: O(logn), n = len(nums) + - Space Complexity: O(1) + """ + def findMin(self, nums: List[int]) -> int: + # Binary Search + l, r = 0, len(nums) - 1 + + while l < r: + mid = (l + r) // 2 + if nums[mid] > nums[r]: + # if min number located in right side + l = mid + 1 + else: + # if min number located in left side (including current pivot) + r = mid + + return nums[l] + +tc = [ + ([3,4,5,1,2], 1), + ([4,5,6,7,0,1,2], 0), + ([11,13,15,17], 11) +] + +for i, (nums, e) in enumerate(tc, 1): + sol = Solution() + r = sol.findMin(nums) + print(f"TC {i} is Passed!" if r == e else f"TC {i} is Failed! - Expected: {e}, Result: {r}") diff --git a/maximum-depth-of-binary-tree/ayosecu.py b/maximum-depth-of-binary-tree/ayosecu.py new file mode 100644 index 000000000..e5dc56766 --- /dev/null +++ b/maximum-depth-of-binary-tree/ayosecu.py @@ -0,0 +1,53 @@ +from typing import Optional + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + """ + - Time Complexity: O(n), n = The number of nodes in tree + - Space Complexity: O(H), H = The height of tree, + - H = logn, if the tree is balanced + - H = n, if the tree is skewed + """ + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + # dfs : count the depth + max_depth = 0 + + def dfs(node, count): + nonlocal max_depth + + if not node: + max_depth = max(max_depth, count) + return + + dfs(node.left, count + 1) + dfs(node.right, count + 1) + + dfs(root, 0) + + return max_depth + +def doTest(): + sol = Solution() + + root1 = TreeNode(3) + root1.left = TreeNode(9) + root1.right = TreeNode(20) + root1.right.left = TreeNode(15) + root1.right.right = TreeNode(7) + print("TC 1 is Success!" if sol.maxDepth(root1) == 3 else "TC 1 is Failed!") + + root2 = TreeNode(1) + root2.right = TreeNode(2) + print(f"TC 2 is Success!" if sol.maxDepth(root2) == 2 else "TC 2 is Failed!") + + print(f"TC 3 is Success!" if sol.maxDepth(None) == 0 else "TC 3 is Failed!") +doTest() diff --git a/merge-two-sorted-lists/ayosecu.py b/merge-two-sorted-lists/ayosecu.py new file mode 100644 index 000000000..7b9c6492d --- /dev/null +++ b/merge-two-sorted-lists/ayosecu.py @@ -0,0 +1,62 @@ +from typing import Optional + +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + +class Solution: + """ + - Time Complexity: O(n + m), n = len(list1), m = len(list2) + - Space Complexity: O(1) + """ + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + # two pointers + p1, p2 = list1, list2 + dummy = ListNode(0) + current = dummy + + while p1 and p2: + if p1.val < p2.val: + current.next = p1 + p1 = p1.next + else: + current.next = p2 + p2 = p2.next + current = current.next + + current.next = p1 if p1 else p2 + + return dummy.next + +def printList(list): + if not list: + print("[]") + return + + str_list = [] + while list: + str_list.append(str(list.val)) + list = list.next + print("[" + ", ".join(str_list) + "]") + +def doTest(): + sol = Solution() + + list1 = ListNode(1) + list1.next = ListNode(2) + list1.next.next = ListNode(4) + list2 = ListNode(1) + list2.next = ListNode(3) + list2.next.next = ListNode(4) + result1 = sol.mergeTwoLists(list1, list2) + printList(result1) + + result2 = sol.mergeTwoLists(None, None) + printList(result2) + + result3 = sol.mergeTwoLists(None, ListNode(0)) + printList(result3) + +doTest() diff --git a/word-search/ayosecu.py b/word-search/ayosecu.py new file mode 100644 index 000000000..257a3693b --- /dev/null +++ b/word-search/ayosecu.py @@ -0,0 +1,52 @@ +from typing import List + +class Solution: + """ + - Time Complexity: O(m*n*3^w) + - m = len(board), n = len(board[0]), w = len(word) + - m * n => finding start point + - 3^w => There are three ways for visiting recursively until find a word + - Space Complexity: O(w) + - The sum of stack's space => The depth of dfs => len(word) + """ + def exist(self, board: List[List[str]], word: str) -> bool: + m, n = len(board), len(board[0]) + + # DFS approach + def dfs(i, j, leng): + if leng == len(word): + # Found! + return True + + if not (0 <= i < m and 0 <= j < n) or board[i][j] != word[leng]: + # Wrong position or Not matched + return False + + temp = board[i][j] # Backup + board[i][j] = "#" # Visited + for dx, dy in [(1, 0), (0, 1), (-1, 0), (0, -1)]: + if dfs(i + dx, j + dy, leng + 1): + return True + board[i][j] = temp # Restore + + return False + + # Finding Start Point + for i in range(m): + for j in range(n): + if word[0] == board[i][j]: + if dfs(i, j, 0): + return True + + return False + +tc = [ + ([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCED", True), + ([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "SEE", True), + ([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCB", False) +] + +for i, (board, word, e) in enumerate(tc, 1): + sol = Solution() + r = sol.exist(board, word) + print(f"TC {i} is Passed!" if r == e else f"TC {i} is Failed! - Expected: {e}, Result: {r}")