diff --git a/best-time-to-buy-and-sell-stock/ayosecu.py b/best-time-to-buy-and-sell-stock/ayosecu.py new file mode 100644 index 000000000..4eb57dd47 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/ayosecu.py @@ -0,0 +1,25 @@ +from typing import List +class Solution: + """ + - Time Complexity: O(n), n = len(prices) + - Space Complexity: O(1) + """ + def maxProfit(self, prices: List[int]) -> int: + min_price = float("inf") + max_profit = 0 + + for price in prices: + min_price = min(min_price, price) + max_profit = max(max_profit, price - min_price) + + return max_profit + +tc = [ + ([7,1,5,3,6,4], 5), + ([7,6,4,3,1], 0) +] + +for i, (prices, e) in enumerate(tc, 1): + sol = Solution() + r = sol.maxProfit(prices) + print(f"TC {i} is Passed!" if r == e else f"TC {i} is Failed! - Expected: {e}, Result: {r}") diff --git a/encode-and-decode-strings/ayosecu.py b/encode-and-decode-strings/ayosecu.py new file mode 100644 index 000000000..ef5d36a81 --- /dev/null +++ b/encode-and-decode-strings/ayosecu.py @@ -0,0 +1,49 @@ +class Solution: + """ + @param: strs: a list of strings + @return: encodes a list of strings to a single string. + - Time Complexity: O(N), N = All characters in strs + - Space Complexity: O(N) + """ + def encode(self, strs): + # Encode Format: xx#str + # xx:len(s) + # strs = ["abc", "defg"] + # Encoded String = 3#abc4#defg + enc_list = [] + for s in strs: + enc_list.append(f"{len(s)}#{s}") + return "".join(enc_list) + + """ + @param: str: A string + @return: decodes a single string to a list of strings + - Time Complexity: O(n), n = len(str) + - Space Complexity: O(1), if output is excluded. + """ + def decode(self, str): + result = [] + + i = 0 + while i < len(str): + j = i + while str[j] != "#": + j += 1 + n = int(str[i:j]) + i = j + 1 + result.append(str[i:i + n]) + i += n + + return result + +tc = [ + (["lint","code","love","you"], "4#lint4#code4#love3#you"), + (["we", "say", ":", "yes"], "2#we3#say1#:3#yes") +] + +for i, (p1, p2) in enumerate(tc, 1): + sol = Solution() + r = sol.encode(p1) + print(f"TC {i} - encode() is Passed!" if r == p2 else f"TC {i} - encode() is Failed! - Expected:{p2}, Result: {r}") + r = sol.decode(p2) + print(f"TC {i} - decode() is Passed!" if r == p1 else f"TC {i} - decode() is Failed! - Expected:{p1}, Result: {r}") diff --git a/group-anagrams/ayosecu.py b/group-anagrams/ayosecu.py new file mode 100644 index 000000000..406846255 --- /dev/null +++ b/group-anagrams/ayosecu.py @@ -0,0 +1,32 @@ +from typing import List +from collections import defaultdict + +class Solution: + """ + - Time Complexity: O(nklogk), n = len(strs), k = Max of len(strs[i]) + - for loop => O(n) + - sorted(s) => O(klogk) + - Space Complexity: O(nk), dictionary size + """ + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + # dictionary + dic = defaultdict(list) + + for s in strs: + ss = "".join(sorted(s)) + dic[ss].append(s) + + return list(dic.values()) + +tc = [ + (["eat","tea","tan","ate","nat","bat"], [["bat"],["nat","tan"],["ate","eat","tea"]]), + ([""], [[""]]), + (["a"], [["a"]]) +] + +for i, (strs, e) in enumerate(tc, 1): + sol = Solution() + r = sol.groupAnagrams(strs) + r_sorted = sorted([sorted(group) for group in r]) + e_sorted = sorted([sorted(group) for group in e]) + print(f"TC {i} is Passed!" if r_sorted == e_sorted else f"TC {i} is Failed! - Expected: {e_sorted}, Result: {r_sorted}") diff --git a/implement-trie-prefix-tree/ayosecu.py b/implement-trie-prefix-tree/ayosecu.py new file mode 100644 index 000000000..ebec6bf45 --- /dev/null +++ b/implement-trie-prefix-tree/ayosecu.py @@ -0,0 +1,72 @@ +class TrieNode: + def __init__(self): + self.children = {} + self.isEnd = False + +class Trie: + # Init Structure + def __init__(self): + self.root = TrieNode() + + # Time Complexity: O(n), n = len(word) + # Space Complexity: O(n) + def insert(self, word: str) -> None: + current = self.root + for c in word: + if c not in current.children: + current.children[c] = TrieNode() + current = current.children[c] + current.isEnd = True + + # Time Complexity: O(n), n = len(word) + # Space Complexity: O(1) + def search(self, word: str) -> bool: + current = self.root + for c in word: + if c not in current.children: + return False + current = current.children[c] + return current.isEnd # Check whole characters were matched + + # Time Complexity: O(n), n = len(prefix) + # Space Complexity: O(1) + def startsWith(self, prefix: str) -> bool: + current = self.root + for c in prefix: + if c not in current.children: + return False + current = current.children[c] + return True + + +tc = [ + ("insert", "apple", None), + ("search", "apple", True), + ("search", "app", False), + ("startsWith", "app", True), + ("insert", "app", None), + ("search", "app", True), + ("insert", "banana", None), + ("search", "banana", True), + ("search", "bananas", False), + ("startsWith", "ban", True), + ("startsWith", "baz", False), + ("search", "", False), + ("startsWith", "", True) +] + +trie = Trie() +for i, (op, value, expected) in enumerate(tc, 1): + if op == "insert": + result = trie.insert(value) + elif op == "search": + result = trie.search(value) + elif op == "startsWith": + result = trie.startsWith(value) + else: + result = None # unknown operation + + if result == expected: + print(f"TC {i} is Passed!") + else: + print(f"TC {i} is Failed! - Op: {op}('{value}'), Expected: {expected}, Result: {result}") diff --git a/word-break/ayosecu.py b/word-break/ayosecu.py new file mode 100644 index 000000000..c002db46a --- /dev/null +++ b/word-break/ayosecu.py @@ -0,0 +1,35 @@ +from typing import List + +class Solution: + """ + - Time Complexity: O(n^2), n = len(s) + - Space Complexity: O(n + m) + - n = len(s) = dp size + - m = The number of characters in wordDict (wordDict size) + """ + def wordBreak(self, s: str, wordDict: List[str]) -> bool: + n = len(s) + wordDict = set(wordDict) + + # Use DP: dp[i] => s[0:i] is possible to be seperated by dictionary words + dp = [False] * (n + 1) + dp[0] = True + + for i in range(1, n + 1): + for j in range(i): + if dp[j] and s[j:i] in wordDict: + dp[i] = True + break # s[i-1] is possible => don't need to check forward string + + return dp[-1] # check s[0:n] + +tc = [ + ("leetcode", ["leet","code"], True), + ("applepenapple", ["apple","pen"], True), + ("catsandog", ["cats","dog","sand","and","cat"], False) +] + +sol = Solution() +for i, (s, wordDict, e) in enumerate(tc, 1): + r = sol.wordBreak(s, wordDict) + print(f"TC {i} is Passed!" if r == e else f"TC {i} is Failed! - Expected: {e}, Result: {r}")