diff --git a/combination-sum/dolphinflow86.py b/combination-sum/dolphinflow86.py new file mode 100644 index 0000000000..b44b1d9892 --- /dev/null +++ b/combination-sum/dolphinflow86.py @@ -0,0 +1,27 @@ +# 1) Backtrack every possible combination to find subsets that match the target condition. +# TC: O(N^(T/M)) where N is the length of candidates, M is the minimum value in candidates, and T is the target number. +# SC: O(T/M) - The maximum depth of the recursion stack. +class Solution: + def backtrack(self, candidates: List[int], remain: int, start_index: int, path:List[int], answer: List[List[int]]): + if remain == 0: + answer.append(path[:]) + return + + cur = candidates[start_index] + + for i in range(start_index, len(candidates)): + if remain < candidates[i]: + break + + path.append(candidates[i]) + self.backtrack(candidates, remain - candidates[i], i, path, answer) + path.pop() + + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + path = [] + answer = [] + + candidates.sort() + self.backtrack(candidates, target, 0, path, answer) + + return answer diff --git a/decode-ways/dolphinflow86.py b/decode-ways/dolphinflow86.py new file mode 100644 index 0000000000..51f1af419b --- /dev/null +++ b/decode-ways/dolphinflow86.py @@ -0,0 +1,28 @@ +# 1) Top-down DP (Recursion + Memoization) +# At each step, recurse down one and two digit case. Memoization is required due to overlapping subproblems. +# TC: O(N) where N is the length of the string +# SC: O(N) where N is the length of the string (recursion stack space and memo array) +class Solution: + def decode(self, s: str, idx: int, memo: List[int]) -> int: + if idx == len(s): return 1 + if idx > len(s): return 0 + if int(s[idx]) == 0: return 0 + + if memo[idx] != -1: return memo[idx] + + # 1 digit + ways = self.decode(s, idx + 1, memo) + + # 2 digits + if idx + 2 <= len(s): + num = int(s[idx:idx+2]) + if 10 <= num <= 26: + ways += self.decode(s, idx + 2, memo) + + memo[idx] = ways + return ways + + def numDecodings(self, s: str) -> int: + # 11106 + memo = [-1] * len(s) + return self.decode(s, 0, memo) diff --git a/maximum-subarray/dolphinflow86.py b/maximum-subarray/dolphinflow86.py new file mode 100644 index 0000000000..d5e3c93627 --- /dev/null +++ b/maximum-subarray/dolphinflow86.py @@ -0,0 +1,17 @@ +# 1) First of all, I tried to come up with a solution for a while but failed eventually. +# I got some hints from AI and then it was Kadane's algorithm. Calculate accumulated sum while iterating +# compare with the current number, if the current number is greater than accumulated sum + current number +# # reset accoumulted sum with current number. Otherwise update with new sum. +# TC: O(N) where N is the size of the nums array +# SC: O(1) +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + if n == 1: return nums[0] + + prev_sum = nums[0] + max_sum = prev_sum + for i in range(1, n): + prev_sum = max(prev_sum + nums[i], nums[i]) + max_sum = max(max_sum, prev_sum) + return max_sum diff --git a/number-of-1-bits/dolphinflow86.py b/number-of-1-bits/dolphinflow86.py new file mode 100644 index 0000000000..6795f646d0 --- /dev/null +++ b/number-of-1-bits/dolphinflow86.py @@ -0,0 +1,11 @@ +# 1) Divide by 2 and count set bit. +# TC: O(logN) where N is the given number. +# SC: O(1) +class Solution: + def hammingWeight(self, n: int) -> int: + setbit_count = 1 + + while n >= 2: + if n % 2 == 1: setbit_count += 1 + n = n // 2 + return setbit_count diff --git a/valid-palindrome/dolphinflow86.py b/valid-palindrome/dolphinflow86.py new file mode 100644 index 0000000000..02fafa858e --- /dev/null +++ b/valid-palindrome/dolphinflow86.py @@ -0,0 +1,42 @@ +# 1) Iterate through the string using two-pointers, skipping non-alphanumeric characters and comparing them in lowercase to validate the palindrome in-place. +# TC: O(N) where N is the length of s +# SC: O(1) +class Solution: + def isPalindrome(self, s: str) -> bool: + left = 0 + right = len(s) - 1 + + while left < right: + if not s[left].isalnum(): + left += 1 + continue + if not s[right].isalnum(): + right -= 1 + continue + + if s[left].lower() != s[right].lower(): return False + left += 1 + right -= 1 + + return True + +# 2) Filter alphanumeric characters and conver them to lowercase to create a new string and then simply validate palindrome using two-pointers +# TC: O(N) where N is the length of s +# SC: O(N) where N is the length of s +class Solution: + def isPalindrome(self, s: str) -> bool: + new_str = "" + for ch in s: + if ch.isalnum(): + new_str += ch.lower() + + n = len(new_str) + left = 0 + right = n - 1 + + while left < right: + if new_str[left] != new_str[right]: return False + left += 1 + right -= 1 + + return True