From 4d5f4280a3c17bee641071a5b59a9c6329c625bf Mon Sep 17 00:00:00 2001 From: woo Date: Sat, 27 Jun 2026 23:26:53 +0900 Subject: [PATCH 01/14] week 1 --- contains-duplicate/alphaorderly.py | 9 ++++++ house-robber/alphaorderly.py | 16 ++++++++++ longest-consecutive-sequence/alphaorderly.py | 33 ++++++++++++++++++++ top-k-frequent-elements/alphaorderly.py | 14 +++++++++ two-sum/alphaorderly.py | 11 +++++++ 5 files changed, 83 insertions(+) create mode 100644 contains-duplicate/alphaorderly.py create mode 100644 house-robber/alphaorderly.py create mode 100644 longest-consecutive-sequence/alphaorderly.py create mode 100644 top-k-frequent-elements/alphaorderly.py create mode 100644 two-sum/alphaorderly.py diff --git a/contains-duplicate/alphaorderly.py b/contains-duplicate/alphaorderly.py new file mode 100644 index 0000000000..3c1bc7e267 --- /dev/null +++ b/contains-duplicate/alphaorderly.py @@ -0,0 +1,9 @@ +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + counter = set() + for num in nums: + if num in counter: + return True + else: + counter.add(num) + return False diff --git a/house-robber/alphaorderly.py b/house-robber/alphaorderly.py new file mode 100644 index 0000000000..6876b82580 --- /dev/null +++ b/house-robber/alphaorderly.py @@ -0,0 +1,16 @@ +class Solution: + def rob(self, nums: List[int]) -> int: + + if len(nums) == 1: + return nums[0] + + dp = [0] * len(nums) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + max_value = nums[0] + + for i in range(2, len(nums)): + dp[i] = max(max(max_value, dp[i - 2]) + nums[i], dp[i - 1]) + + return dp[-1] diff --git a/longest-consecutive-sequence/alphaorderly.py b/longest-consecutive-sequence/alphaorderly.py new file mode 100644 index 0000000000..d1045d7059 --- /dev/null +++ b/longest-consecutive-sequence/alphaorderly.py @@ -0,0 +1,33 @@ +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + + if len(nums) == 0: + return 0 + + s: set[int] = set() + d: dict[int, int] = {} + + large = -1 + + for num in nums: + s.add(num) + + for num in nums: + if num not in s: + continue + if len(s) == 0: + break + streak = 1 + s.remove(num) + for i in range(num - 1, -(10**9) - 1, -1): + if i in s: + s.remove(i) + streak += 1 + continue + elif i in d: + streak += d[i] + break + d[num] = streak + large = max(large, streak) + + return large diff --git a/top-k-frequent-elements/alphaorderly.py b/top-k-frequent-elements/alphaorderly.py new file mode 100644 index 0000000000..48c21aabeb --- /dev/null +++ b/top-k-frequent-elements/alphaorderly.py @@ -0,0 +1,14 @@ +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + cntr = Counter(nums) + + cntr_list = [(-b, a) for a, b in list(cntr.items())] + + heapify(cntr_list) + + ans = [] + + for _ in range(k): + ans.append(heappop(cntr_list)[1]) + + return ans diff --git a/two-sum/alphaorderly.py b/two-sum/alphaorderly.py new file mode 100644 index 0000000000..e353a536e7 --- /dev/null +++ b/two-sum/alphaorderly.py @@ -0,0 +1,11 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + seen = {} + + for i, num in enumerate(nums): + need = target - num + + if need in seen: + return [seen[need], i] + + seen[num] = i From 3ac63f595cde69fb1dfc36fe617cd375a6d2a0dd Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 28 Jun 2026 11:40:03 +0900 Subject: [PATCH 02/14] [alphaorderly] WEEK 02 Solutions --- 3sum/alphaorderly.py | 37 +++++++++++ climbing-stairs/alphaorderly.py | 66 ++++++++++++++++++++ product-of-array-except-self/alphaorderly.py | 37 +++++++++++ valid-anagram/alphaorderly.py | 13 ++++ validate-binary-search-tree/alphaorderly.py | 38 +++++++++++ 5 files changed, 191 insertions(+) create mode 100644 3sum/alphaorderly.py create mode 100644 climbing-stairs/alphaorderly.py create mode 100644 product-of-array-except-self/alphaorderly.py create mode 100644 valid-anagram/alphaorderly.py create mode 100644 validate-binary-search-tree/alphaorderly.py diff --git a/3sum/alphaorderly.py b/3sum/alphaorderly.py new file mode 100644 index 0000000000..fded8856a5 --- /dev/null +++ b/3sum/alphaorderly.py @@ -0,0 +1,37 @@ +class Solution: + def threeSum(self, nums: list[int]) -> list[list[int]]: + """ + O(N^2) + """ + cntr = Counter(nums) + + ans = [] + + # First case -> [0, 0, 0] Triplet + if cntr[0] >= 3: + ans.append([0, 0, 0]) + + # Second case -> two same numbers + one diff number + for k, v in cntr.items(): + if k == 0: + continue + if v >= 2 and -(k * 2) in cntr: + ans.append([k, k, -(k * 2)]) + + s = set(nums) + nums = list(s) + nums.sort() + + pos = {k: v for v, k in enumerate(nums)} + N = len(nums) + + # Third case -> all different numbers + for i in range(N - 2): + for j in range(i + 1, N - 1): + target = -(nums[i] + nums[j]) + if target in pos: + k = pos[target] + if k > j: + ans.append([nums[i], nums[j], nums[k]]) + + return ans diff --git a/climbing-stairs/alphaorderly.py b/climbing-stairs/alphaorderly.py new file mode 100644 index 0000000000..7c885a2616 --- /dev/null +++ b/climbing-stairs/alphaorderly.py @@ -0,0 +1,66 @@ +# class Solution: +# def climbStairs(self, n: int) -> int: +# """ +# O(N) with additional space +# """ +# if n <= 2: +# return n + +# dp = [0] * (n + 1) +# dp[1] = 1 +# dp[2] = 2 + +# for i in range(3, n + 1): +# dp[i] = dp[i - 1] + dp[i - 2] + +# return dp[-1] + +# class Solution: +# """ +# O(N) Found that solution is fibonacci number +# """ +# def climbStairs(self, n: int) -> int: +# if n <= 2: +# return n + +# p1, p2 = 1, 2 +# for i in range(3, n + 1): +# p1, p2 = p2, p1 + p2 + +# return p2 + + +# Fibonacci hack +class Solution: + def climbStairs(self, n: int) -> int: + """ + O(Log N) + """ + + # O(1) operation + def mat_mul(a: List[List[int]], b: List[List[int]]) -> List[List[int]]: + ans = [[0] * 2 for _ in range(2)] + + for i in range(2): + for j in range(2): + for k in range(2): + ans[i][j] += a[i][k] * b[k][j] + + return ans + + # O(Log N) operation + def mat_pow(a: List[List[int]], n: int) -> List[List[int]]: + if n == 1: + return [[1, 1], [1, 0]] + + half = mat_pow(a, n // 2) + multed = mat_mul(half, half) + + if n % 2: + return mat_mul(multed, [[1, 1], [1, 0]]) + else: + return multed + + ans = mat_pow([[1, 1], [1, 0]], n) + + return ans[0][0] diff --git a/product-of-array-except-self/alphaorderly.py b/product-of-array-except-self/alphaorderly.py new file mode 100644 index 0000000000..98990e6eba --- /dev/null +++ b/product-of-array-except-self/alphaorderly.py @@ -0,0 +1,37 @@ +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + """ + O(N) Time complexity + O(N) Space complexity + + If output array does not count as extra space as written in follow up, + it is O(1) solution + """ + N = len(nums) + + z_count = 0 + multed = 1 + + # 1. Create a multiplied number contains all array integers + # - Count zero for edge case + for n in nums: + if n == 0: + z_count += 1 + if z_count > 1: + return [0] * N + continue + + multed *= n + + ans = [0] * N + + # 2. Generate ans array with edge case ( 1 zero number ) + for i, n in enumerate(nums): + if z_count == 1: + if n == 0: + ans[i] = multed + continue + + ans[i] = multed // n + + return ans diff --git a/valid-anagram/alphaorderly.py b/valid-anagram/alphaorderly.py new file mode 100644 index 0000000000..2c2321ebbd --- /dev/null +++ b/valid-anagram/alphaorderly.py @@ -0,0 +1,13 @@ +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + """ + O(N Log N) + """ + return sorted(s) == sorted(t) + +# class Solution: +# """ +# O(N) +# """ +# def isAnagram(self, s: str, t: str) -> bool: +# return Counter(s) == Counter(t) diff --git a/validate-binary-search-tree/alphaorderly.py b/validate-binary-search-tree/alphaorderly.py new file mode 100644 index 0000000000..0c9a359745 --- /dev/null +++ b/validate-binary-search-tree/alphaorderly.py @@ -0,0 +1,38 @@ +# 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: +# def isValidBST(self, root: Optional[TreeNode], lower: Optional[int] = -float('inf'), upper: Optional[int] = float('inf')) -> bool: +# if not root: +# return True + +# if root.val <= lower or root.val >= upper: +# return False + +# return self.isValidBST(root.left, lower, root.val) and self.isValidBST(root.right, root.val, upper) + + +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + """ + O(N) + """ + s = [(root, -float("inf"), float(inf))] + + while s: + node, lower, upper = s.pop() + + if node.val <= lower or node.val >= upper: + return False + + if node.left: + s.append((node.left, lower, node.val)) + + if node.right: + s.append((node.right, node.val, upper)) + + return True From 612dbbbc118bf769b50a7bdc870bb107ab7afa6b Mon Sep 17 00:00:00 2001 From: woo Date: Mon, 29 Jun 2026 00:38:22 +0900 Subject: [PATCH 03/14] =?UTF-8?q?fix:=20description=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EA=B2=8C=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- product-of-array-except-self/alphaorderly.py | 48 ++++++++++---------- validate-binary-search-tree/alphaorderly.py | 2 +- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/product-of-array-except-self/alphaorderly.py b/product-of-array-except-self/alphaorderly.py index 98990e6eba..9c950226c5 100644 --- a/product-of-array-except-self/alphaorderly.py +++ b/product-of-array-except-self/alphaorderly.py @@ -2,36 +2,34 @@ class Solution: def productExceptSelf(self, nums: List[int]) -> List[int]: """ O(N) Time complexity - O(N) Space complexity - - If output array does not count as extra space as written in follow up, - it is O(1) solution """ N = len(nums) - z_count = 0 - multed = 1 - - # 1. Create a multiplied number contains all array integers - # - Count zero for edge case - for n in nums: - if n == 0: - z_count += 1 - if z_count > 1: - return [0] * N - continue + zeroes = nums.count(0) - multed *= n + if zeroes > 1: + return [0] * N ans = [0] * N - - # 2. Generate ans array with edge case ( 1 zero number ) - for i, n in enumerate(nums): - if z_count == 1: - if n == 0: - ans[i] = multed - continue - - ans[i] = multed // n + acc = 1 + + # This could make logic complex, so treat it separately + if zeroes == 1: + place = nums.index(0) + for i in range(N): + if i != place: + acc *= nums[i] + ans[place] = acc + return ans + + for i in range(N): + ans[i] = acc + acc *= nums[i] + + acc = 1 + + for i in range(N - 1, -1, -1): + ans[i] *= acc + acc *= nums[i] return ans diff --git a/validate-binary-search-tree/alphaorderly.py b/validate-binary-search-tree/alphaorderly.py index 0c9a359745..2d8461030f 100644 --- a/validate-binary-search-tree/alphaorderly.py +++ b/validate-binary-search-tree/alphaorderly.py @@ -21,7 +21,7 @@ def isValidBST(self, root: Optional[TreeNode]) -> bool: """ O(N) """ - s = [(root, -float("inf"), float(inf))] + s = [(root, -float("inf"), float("inf"))] while s: node, lower, upper = s.pop() From a7c2098206acef7f99d1aa93a5d3e8f661db8f3a Mon Sep 17 00:00:00 2001 From: woo Date: Mon, 29 Jun 2026 16:04:49 +0900 Subject: [PATCH 04/14] =?UTF-8?q?fix:=20=EC=A2=80=20=EB=8D=94=20=EA=B0=84?= =?UTF-8?q?=EA=B2=B0=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- product-of-array-except-self/alphaorderly.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/product-of-array-except-self/alphaorderly.py b/product-of-array-except-self/alphaorderly.py index 9c950226c5..62854a39e7 100644 --- a/product-of-array-except-self/alphaorderly.py +++ b/product-of-array-except-self/alphaorderly.py @@ -5,22 +5,9 @@ def productExceptSelf(self, nums: List[int]) -> List[int]: """ N = len(nums) - zeroes = nums.count(0) - - if zeroes > 1: - return [0] * N - ans = [0] * N - acc = 1 - # This could make logic complex, so treat it separately - if zeroes == 1: - place = nums.index(0) - for i in range(N): - if i != place: - acc *= nums[i] - ans[place] = acc - return ans + acc = 1 for i in range(N): ans[i] = acc From 3855235abd883716ede1dc7fc347402432361782 Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:07:29 +0900 Subject: [PATCH 05/14] [alphaorderly] WEEK 03 Solutions --- combination-sum/alphaorderly.py | 51 ++++++++++++++++++++++ decode-ways/alphaorderly.py | 31 ++++++++++++++ maximum-subarray/alphaorderly.py | 72 ++++++++++++++++++++++++++++++++ number-of-1-bits/alphaorderly.py | 7 ++++ valid-palindrome/alphaorderly.py | 5 +++ 5 files changed, 166 insertions(+) create mode 100644 combination-sum/alphaorderly.py create mode 100644 decode-ways/alphaorderly.py create mode 100644 maximum-subarray/alphaorderly.py create mode 100644 number-of-1-bits/alphaorderly.py create mode 100644 valid-palindrome/alphaorderly.py diff --git a/combination-sum/alphaorderly.py b/combination-sum/alphaorderly.py new file mode 100644 index 0000000000..2ab9b68f50 --- /dev/null +++ b/combination-sum/alphaorderly.py @@ -0,0 +1,51 @@ + +""" +Time Complexity: O(N^target) +Space Complexity: O(target) + +Classic backtracking approach. +- Use a helper function to backtrack and generate all possible combinations. +""" +# class Solution: +# def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: +# N = len(candidates) +# candidates.sort() + +# ans = [] +# app = [] + +# def backtracking(last: int, left: int) -> None: +# if left == 0: +# ans.append(app[:]) +# return + +# for i in range(last, N): +# if candidates[i] > left: +# continue + +# app.append(candidates[i]) +# backtracking(i, left - candidates[i]) +# app.pop() + +# backtracking(0, target) + +# return ans + +""" +Time Complexity: O(N * target) +Space Complexity: O(target) + +- Use a dynamic programming approach to store the combinations that sum to each target. +- dp[j] is a list of lists that sum to j. +""" +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + dp = [list() for _ in range(target + 1)] + dp[0] = [[]] + + for c in candidates: + for j in range(c, target + 1): + for partial in dp[j - c]: + dp[j].append(partial + [c]) + + return dp[-1] diff --git a/decode-ways/alphaorderly.py b/decode-ways/alphaorderly.py new file mode 100644 index 0000000000..123e80b1b7 --- /dev/null +++ b/decode-ways/alphaorderly.py @@ -0,0 +1,31 @@ +""" +Time Complexity: O(N) +Space Complexity: O(1) + +prev_2 : number of ways to decode the string ending with the previous two characters +prev_1 : number of ways to decode the string ending with the previous character +new_prev : number of ways to decode the string ending with the current character +""" +class Solution: + def numDecodings(self, s: str) -> int: + N = len(s) + + if s[0] == "0": + return 0 + + if N == 1: + return 1 + + prev_2 = 1 + prev_1 = int(1 <= int(s[0] + s[1]) <= 26) + int(s[1] != "0") + + for i in range(2, N): + new_prev = 0 + if 1 <= int(s[i - 1] + s[i]) <= 26 and s[i - 1] != "0": + new_prev += prev_2 + if s[i] != "0": + new_prev += prev_1 + + prev_2, prev_1 = prev_1, new_prev + + return prev_1 diff --git a/maximum-subarray/alphaorderly.py b/maximum-subarray/alphaorderly.py new file mode 100644 index 0000000000..d553945d9d --- /dev/null +++ b/maximum-subarray/alphaorderly.py @@ -0,0 +1,72 @@ + + +""" +Time Complexity: O(NLogN) +Space Complexity: O(N) ( Reason: Recursive stack pointer for every element ) + +Divide and Conquer Approach + +1. Divide the array into two halves +2. Find the maximum subarray sum in the left half +3. Find the maximum subarray sum in the right half +4. Find the maximum subarray sum that crosses the midpoint +5. Return the maximum of the three sums +""" +# class Solution: +# def maxSubArray(self, nums: List[int]) -> int: + +# def divide(start: int, end: int) -> int: +# if start >= end: +# return nums[start] + +# mid = (start + end) // 2 + +# left = divide(start, mid) +# right = divide(mid + 1, end) + +# left_largest = -float('inf') +# right_largest = -float('inf') + +# left_acc = 0 +# right_acc = 0 + +# left_index = mid +# right_index = mid + 1 + +# while left_index >= start: +# left_acc += nums[left_index] +# left_largest = max(left_largest, left_acc) +# left_index -= 1 + +# while right_index <= end: +# right_acc += nums[right_index] +# right_largest = max(right_largest, right_acc) +# right_index += 1 + +# return max(left_largest + right_largest, left, right) + +# return divide(0, len(nums) - 1) + + + + +""" +Time Complexity: O(N) +Space Complexity: O(1) + +prev : maximum sum of the subarray ending with the previous element +ans : maximum sum of the subarray +curr : maximum sum of the subarray ending with the current element +""" +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + N = len(nums) + prev = nums[0] + ans = nums[0] + + for i in range(1, N): + curr = max(nums[i], prev + nums[i]) + prev = curr + ans = max(ans, curr) + + return ans diff --git a/number-of-1-bits/alphaorderly.py b/number-of-1-bits/alphaorderly.py new file mode 100644 index 0000000000..98a9e620a5 --- /dev/null +++ b/number-of-1-bits/alphaorderly.py @@ -0,0 +1,7 @@ +class Solution: + def hammingWeight(self, n: int) -> int: + ans = 0 + while n: + ans += n & 1 + n >>= 1 + return ans \ No newline at end of file diff --git a/valid-palindrome/alphaorderly.py b/valid-palindrome/alphaorderly.py new file mode 100644 index 0000000000..c6180a8e8f --- /dev/null +++ b/valid-palindrome/alphaorderly.py @@ -0,0 +1,5 @@ +class Solution: + def isPalindrome(self, s: str) -> bool: + processed = "".join(ch.lower() for ch in s if ch.isalnum()) + + return processed == processed[::-1] \ No newline at end of file From b1de0e19837ad43fa1f0ef8a759efc4a3ed2e734 Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:14:32 +0900 Subject: [PATCH 06/14] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- maximum-subarray/alphaorderly.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/maximum-subarray/alphaorderly.py b/maximum-subarray/alphaorderly.py index d553945d9d..7ccc23d8f8 100644 --- a/maximum-subarray/alphaorderly.py +++ b/maximum-subarray/alphaorderly.py @@ -65,8 +65,7 @@ def maxSubArray(self, nums: List[int]) -> int: ans = nums[0] for i in range(1, N): - curr = max(nums[i], prev + nums[i]) - prev = curr - ans = max(ans, curr) + prev = max(nums[i], prev + nums[i]) + ans = max(ans, prev) return ans From f9bf16cb75e9c58df9cf6d52d04a932e09683566 Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:16:16 +0900 Subject: [PATCH 07/14] =?UTF-8?q?fix:=20=EC=A4=84=EB=B0=94=EA=BF=88=20?= =?UTF-8?q?=EB=A6=B0=ED=8A=B8=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- number-of-1-bits/alphaorderly.py | 3 ++- valid-palindrome/alphaorderly.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/number-of-1-bits/alphaorderly.py b/number-of-1-bits/alphaorderly.py index 98a9e620a5..728d586e4f 100644 --- a/number-of-1-bits/alphaorderly.py +++ b/number-of-1-bits/alphaorderly.py @@ -4,4 +4,5 @@ def hammingWeight(self, n: int) -> int: while n: ans += n & 1 n >>= 1 - return ans \ No newline at end of file + return ans + \ No newline at end of file diff --git a/valid-palindrome/alphaorderly.py b/valid-palindrome/alphaorderly.py index c6180a8e8f..5272e466bc 100644 --- a/valid-palindrome/alphaorderly.py +++ b/valid-palindrome/alphaorderly.py @@ -2,4 +2,5 @@ class Solution: def isPalindrome(self, s: str) -> bool: processed = "".join(ch.lower() for ch in s if ch.isalnum()) - return processed == processed[::-1] \ No newline at end of file + return processed == processed[::-1] + \ No newline at end of file From de3390f53f6e5b3526745f40dd5512b1ff171f3f Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:16:16 +0900 Subject: [PATCH 08/14] [alphaorderly] WEEK 03 Solutions --- number-of-1-bits/alphaorderly.py | 3 ++- valid-palindrome/alphaorderly.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/number-of-1-bits/alphaorderly.py b/number-of-1-bits/alphaorderly.py index 98a9e620a5..728d586e4f 100644 --- a/number-of-1-bits/alphaorderly.py +++ b/number-of-1-bits/alphaorderly.py @@ -4,4 +4,5 @@ def hammingWeight(self, n: int) -> int: while n: ans += n & 1 n >>= 1 - return ans \ No newline at end of file + return ans + \ No newline at end of file diff --git a/valid-palindrome/alphaorderly.py b/valid-palindrome/alphaorderly.py index c6180a8e8f..5272e466bc 100644 --- a/valid-palindrome/alphaorderly.py +++ b/valid-palindrome/alphaorderly.py @@ -2,4 +2,5 @@ class Solution: def isPalindrome(self, s: str) -> bool: processed = "".join(ch.lower() for ch in s if ch.isalnum()) - return processed == processed[::-1] \ No newline at end of file + return processed == processed[::-1] + \ No newline at end of file From 17669b6090fa6a988bdafa06a7a3ca0237e22a30 Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:22:35 +0900 Subject: [PATCH 09/14] =?UTF-8?q?fix:=20=EB=A6=B0=ED=8A=B8=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- number-of-1-bits/alphaorderly.py | 1 - valid-palindrome/alphaorderly.py | 1 - 2 files changed, 2 deletions(-) diff --git a/number-of-1-bits/alphaorderly.py b/number-of-1-bits/alphaorderly.py index 728d586e4f..edeb621a00 100644 --- a/number-of-1-bits/alphaorderly.py +++ b/number-of-1-bits/alphaorderly.py @@ -5,4 +5,3 @@ def hammingWeight(self, n: int) -> int: ans += n & 1 n >>= 1 return ans - \ No newline at end of file diff --git a/valid-palindrome/alphaorderly.py b/valid-palindrome/alphaorderly.py index 5272e466bc..40adce8416 100644 --- a/valid-palindrome/alphaorderly.py +++ b/valid-palindrome/alphaorderly.py @@ -3,4 +3,3 @@ def isPalindrome(self, s: str) -> bool: processed = "".join(ch.lower() for ch in s if ch.isalnum()) return processed == processed[::-1] - \ No newline at end of file From d8b590322c2eeac2e809a296b15504edc596a2a1 Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:30:48 +0900 Subject: [PATCH 10/14] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=B4=EC=8D=AC=20?= =?UTF-8?q?=EB=82=B4=EC=9E=A5=ED=95=A8=EC=88=98=20=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- number-of-1-bits/alphaorderly.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/number-of-1-bits/alphaorderly.py b/number-of-1-bits/alphaorderly.py index edeb621a00..a334b0b209 100644 --- a/number-of-1-bits/alphaorderly.py +++ b/number-of-1-bits/alphaorderly.py @@ -5,3 +5,7 @@ def hammingWeight(self, n: int) -> int: ans += n & 1 n >>= 1 return ans + +# class Solution: +# def hammingWeight(self, n: int) -> int: +# return bin(n).count('1') From a14205b2cd2fc58b543684b0502a96e9095c66b8 Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 02:38:08 +0900 Subject: [PATCH 11/14] =?UTF-8?q?fix:=20valid-palindrome=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=EC=97=90=20=ED=88=AC=ED=8F=AC=EC=9D=B8=ED=84=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=8B=B5=EC=95=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-palindrome/alphaorderly.py | 41 ++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/valid-palindrome/alphaorderly.py b/valid-palindrome/alphaorderly.py index 40adce8416..5cc3c1b9d5 100644 --- a/valid-palindrome/alphaorderly.py +++ b/valid-palindrome/alphaorderly.py @@ -1,5 +1,42 @@ +""" +Time Complexity: O(N) +Space Complexity: O(N) + +- Process string with lower() and isalnum() to remove non-alphanumeric characters +- Check if the processed string is a palindrome by comparing it to its reverse +""" +# class Solution: +# def isPalindrome(self, s: str) -> bool: +# processed = "".join(ch.lower() for ch in s if ch.isalnum()) + +# return processed == processed[::-1] + +""" +Time Complexity: O(N) +Space Complexity: O(1) + +- Use two pointers to check if the string is a palindrome +- Skip non-alphanumeric characters +- Compare characters from both ends towards the center +""" class Solution: def isPalindrome(self, s: str) -> bool: - processed = "".join(ch.lower() for ch in s if ch.isalnum()) + N = len(s) + + left, right = 0, N - 1 + + while True: + while not s[left].isalnum() and left < right: + left += 1 + while not s[right].isalnum() and left < right: + right -= 1 + + if left >= right: + break + + if s[left].lower() == s[right].lower(): + left, right = left + 1, right - 1 + else: + return False - return processed == processed[::-1] + return True From b087a325bc8692ee2da61de4d409c22756ce312c Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 5 Jul 2026 15:40:26 +0900 Subject: [PATCH 12/14] =?UTF-8?q?fix:=20=EB=A1=9C=EC=A7=81=20=EA=B0=80?= =?UTF-8?q?=EB=8F=85=EC=84=B1=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-palindrome/alphaorderly.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/valid-palindrome/alphaorderly.py b/valid-palindrome/alphaorderly.py index 5cc3c1b9d5..d203dff82f 100644 --- a/valid-palindrome/alphaorderly.py +++ b/valid-palindrome/alphaorderly.py @@ -34,9 +34,9 @@ def isPalindrome(self, s: str) -> bool: if left >= right: break - if s[left].lower() == s[right].lower(): - left, right = left + 1, right - 1 - else: + if s[left].lower() != s[right].lower(): return False + left, right = left + 1, right - 1 + return True From e51ae3713bf7373aedc8b52437184471bd19b04d Mon Sep 17 00:00:00 2001 From: woo Date: Sat, 11 Jul 2026 01:22:05 +0900 Subject: [PATCH 13/14] [alphaorderly] WEEK 04 Solutions - draft --- coin-change/alphaorderly.py | 77 +++++++++ .../alphaorderly.py | 40 +++++ maximum-depth-of-binary-tree/alphaorderly.py | 122 +++++++++++++++ merge-two-sorted-lists/alphaorderly.py | 62 ++++++++ word-search/alphaorderly.py | 147 ++++++++++++++++++ 5 files changed, 448 insertions(+) create mode 100644 coin-change/alphaorderly.py create mode 100644 find-minimum-in-rotated-sorted-array/alphaorderly.py create mode 100644 maximum-depth-of-binary-tree/alphaorderly.py create mode 100644 merge-two-sorted-lists/alphaorderly.py create mode 100644 word-search/alphaorderly.py diff --git a/coin-change/alphaorderly.py b/coin-change/alphaorderly.py new file mode 100644 index 0000000000..50c1187205 --- /dev/null +++ b/coin-change/alphaorderly.py @@ -0,0 +1,77 @@ +""" +Time Complexity: O(n * amount) +Space Complexity: O(n * amount) + +- DP / Top-Down approach +- Use a cache to store the results of the subproblems +""" +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + LARGE = 10 ** 5 + + @cache + def dp(coin: int, left: int) -> int: + if left == 0: + return 0 + + if left < 0: + return LARGE + + if coin >= len(coins): + return LARGE + + a = dp(coin, left - coins[coin]) + 1 + b = dp(coin + 1, left) + + return min(a, b) + + ans = dp(0, amount) + + return ans if ans != LARGE else -1 + +""" +Time Complexity: O(n * amount) +Space Complexity: O(n * amount) + +- DP / Bottom-Up approach +- Use a 2D array to store the results of the subproblems +""" +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + N = len(coins) + dp = [[float('inf')] * (amount + 1) for _ in range(N)] + + for c in range(N): + dp[c][0] = 0 + + if c > 0: + for a in range(amount + 1): + dp[c][a] = dp[c - 1][a] + + for a in range(coins[c], amount + 1): + dp[c][a] = min(dp[c][a], dp[c][a - coins[c]] + 1) + + ans = dp[-1][-1] + + return ans if ans != float('inf') else -1 + +""" +Time Complexity: O(n * amount) +Space Complexity: O(amount) + +- DP / Bottom-Up approach [Space Optimized] +- Use a 1D array to store the results of the subproblems +""" +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + N = len(coins) + dp = [float('inf')] * (amount + 1) + dp[0] = 0 + + for c in range(N): + for a in range(coins[c], amount + 1): + dp[a] = min(dp[a], dp[a - coins[c]] + 1) + + ans = dp[-1] + + return ans if ans != float('inf') else -1 diff --git a/find-minimum-in-rotated-sorted-array/alphaorderly.py b/find-minimum-in-rotated-sorted-array/alphaorderly.py new file mode 100644 index 0000000000..c8e4cf760a --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/alphaorderly.py @@ -0,0 +1,40 @@ +""" +Time Complexity: O(log N) +Space Complexity: O(1) + +### Binary Search Solution ### + +1. Initialize two pointers, left and right, to the start and end of the array +2. While left is less than right, calculate the middle index +3. If nums[mid] > nums[right], search the right half (left = mid + 1) + - Why? mid is in the left sorted portion (larger values), so the rotation point (minimum) must be to the right of mid +4. Otherwise, search the left half including mid (right = mid) + - nums[mid] <= nums[right] means mid is in the right sorted portion or the array is not rotated, so the minimum is at mid or to its left +5. When left == right, return nums[right] +""" +class Solution: + def findMin(self, nums: List[int]) -> int: + N = len(nums) + left, right = 0, N - 1 + + while left < right: + mid = (left + right) // 2 + + if nums[mid] > nums[right]: + left = mid + 1 + else: + right = mid + + return nums[right] + +""" +Time Complexity: O(N) +Space Complexity: O(1) + +### Linear Search Solution ### ( NOT RECOMMENDED ) + +1. Return the minimum element in the array +""" +class Solution: + def findMin(self, nums: List[int]) -> int: + return min(nums) diff --git a/maximum-depth-of-binary-tree/alphaorderly.py b/maximum-depth-of-binary-tree/alphaorderly.py new file mode 100644 index 0000000000..c62ed54197 --- /dev/null +++ b/maximum-depth-of-binary-tree/alphaorderly.py @@ -0,0 +1,122 @@ +# 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 +""" +Time Complexity: O(N) +Space Complexity: O(N) - Recursive stack space + +### Recursive Solution ### + +1. If the root is None, return 0 +2. Return the maximum of the depth of the left and right subtrees + 1 +""" +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1 + +""" +Time Complexity: O(N) +Space Complexity: O(N) - Stack space + +### Iterative Solution ( DFS ) ### + +1. If the root is None, return 0 +2. Use a stack to store the nodes and the level of the nodes +3. Pop the nodes from the stack and update the maximum depth +4. If the node has a left child, add the left child and the level + 1 to the stack +5. If the node has a right child, add the right child and the level + 1 to the stack +6. Return the maximum depth +""" +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + s = [(root, 1)] + ans = 1 + + while s: + node, level = s.pop() + ans = max(ans, level) + + if node.left: + s.append((node.left, level + 1)) + + if node.right: + s.append((node.right, level + 1)) + + return ans + +""" +Time Complexity: O(N) +Space Complexity: O(N) - Queue space + +### Iterative Solution ( BFS ) ### + +1. If the root is None, return 0 +2. Use a queue to store the nodes and the level of the nodes +3. Pop the nodes from the queue and update the maximum depth +4. If the node has a left child, add the left child and the level + 1 to the queue +5. If the node has a right child, add the right child and the level + 1 to the queue +6. Return the maximum depth +""" +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + q = deque([(root, 1)]) + ans = 1 + + while q: + node, level = q.popleft() + ans = max(ans, level) + + if node.left: + q.append((node.left, level + 1)) + + if node.right: + q.append((node.right, level + 1)) + + return ans + +""" +Time Complexity: O(N) +Space Complexity: O(N) - Queue space + +### Iterative Solution ( Level Order Traversal ) ### + +1. If the root is None, return 0 +2. Use a queue to store the nodes +3. Pop the nodes from the queue and update the maximum depth +4. If the node has a left child, add the left child to the queue +5. If the node has a right child, add the right child to the queue +6. Return the maximum depth +""" +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + q = deque([root]) + level = 0 + + while q: + level += 1 + N = len(q) + for _ in range(N): + node = q.popleft() + + if node.left: + q.append(node.left) + + if node.right: + q.append(node.right) + + return level diff --git a/merge-two-sorted-lists/alphaorderly.py b/merge-two-sorted-lists/alphaorderly.py new file mode 100644 index 0000000000..49cca44b58 --- /dev/null +++ b/merge-two-sorted-lists/alphaorderly.py @@ -0,0 +1,62 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +""" +Time Complexity: O(N) +Space Complexity: O(1) + +1. Create a dummy node to store the head of the merged list ( return_node ) +2. Traverse the two lists until one of the lists is empty +3. Compare the values of the two nodes and add the smaller node to the dummy node +4. Move the pointer of the list with the smaller node to the next node +5. Add the remaining nodes of the non-empty list to the dummy node +6. Return the next node of the dummy node +""" +class Solution: + def mergeTwoLists( + self, list1: Optional[ListNode], list2: Optional[ListNode] + ) -> Optional[ListNode]: + head = ListNode() + return_node = head + + while list1 and list2: + if list1.val > list2.val: + head.next = list2 + list2 = list2.next + else: + head.next = list1 + list1 = list1.next + + head = head.next + + if list1: + head.next = list1 + elif list2: + head.next = list2 + + return return_node.next + +""" +Time Complexity: O(N) +Space Complexity: O(N) - Recursive stack space + +1. If one of the lists is empty, return the other list +2. Compare the values of the two nodes and add the smaller node to the merged list +3. Move the pointer of the list with the smaller node to the next node +4. Return the next node of the merged list +""" +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + if not list1: + return list2 + elif not list2: + return list1 + + if list1.val > list2.val: + list2.next = self.mergeTwoLists(list1, list2.next) + return list2 + else: + list1.next = self.mergeTwoLists(list1.next, list2) + return list1 diff --git a/word-search/alphaorderly.py b/word-search/alphaorderly.py new file mode 100644 index 0000000000..d24b070607 --- /dev/null +++ b/word-search/alphaorderly.py @@ -0,0 +1,147 @@ + +""" +Time Complexity: O(N * 4^L) +Space Complexity: O(L) + +### Classic Backtracking Solution ### + +1. Initialize a set to store the cells that have been visited +2. Define a helper function to check if the cell is within the bounds of the board +3. Define a helper function to perform the backtracking +4. If the current index is equal to the length of the word, return True +5. If the cell is out of bounds or the cell does not match the current character, return False +6. Add the cell to the set ( to prevent revisiting the same cell ) +7. Recursively call the helper function for the four possible directions +8. Remove the cell from the set ( backtracking ) +9. Return False ( if the current path does not lead to the target word ) +""" +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + check = set() + ROW, COL = len(board), len(board[0]) + + def bound(r: int, c: int) -> bool: + return 0 <= r < ROW and 0 <= c < COL + + def backtracking(row: int, col: int, n: int) -> bool: + nonlocal check + + if n == len(word): + return True + + if not bound(row, col) or board[row][col] != word[n] or (row, col) in check: + return False + + check.add((row, col)) + if backtracking(row + 1, col, n + 1): + return True + if backtracking(row, col + 1, n + 1): + return True + if backtracking(row - 1, col, n + 1): + return True + if backtracking(row, col - 1, n + 1): + return True + check.remove((row, col)) + + return False + + for row in range(len(board)): + for col in range(len(board[row])): + if backtracking(row, col, 0): + return True + + return False + +""" +Time Complexity: O(N * 4^L) +Space Complexity: O(L) + +### Optimized Backtracking Solution ### + +1. Check if the board is larger than the word size itself +2. Check if the board can assemble the word +3. Make the word to search sparse character first +4. Start the backtracking +5. Check if the cell is within the bounds of the board +6. Check if the cell matches the current character +7. Check if the cell has been visited +8. Mark the cell as visited +9. Recursively call the helper function for the four possible directions +10. Unmark the cell as visited +11. Return False ( if the current path does not lead to the target word ) + + +### Optimizing point ### +1. Check board is larger than word size itself +2. Check board can assemble word +3. Make word to search sparse character first +4. Use check as 2D matrix not set for better performance +""" +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + ROW, COL = len(board), len(board[0]) + N = len(word) + + ### 1. Check board is larger than word size itself + if ROW * COL < len(word): + return False + + ### 2. Check board can assemble word + board_counter = Counter(board[r][c] for r in range(ROW) for c in range(COL)) + word_counter = Counter(word) + + for ch, freq in word_counter.items(): + if board_counter[ch] < freq: + return False + + ### 3. Make word to search sparse character first + if word_counter[word[0]] > word_counter[word[-1]]: + word = word[::-1] + + ### -> START BACKTRCKING <- ### + + ### Prevent overlapping + check = [[False] * COL for _ in range(ROW)] + + ### Define the four + DIR = [ + [-1, 0], + [1, 0], + [0, -1], + [0, 1] + ] + + ### helper function to check bound + def bound(r: int, c: int) -> bool: + return 0 <= r < ROW and 0 <= c < COL + + def backtracking(r: int, c: int, n: int) -> bool: + ### If the current index is equal to the length of the word, return True + if n == N: + return True + + ### If the cell is out of bounds, return False + if not bound(r, c): + return False + + ### If the cell does not match the current character, return False + if word[n] != board[r][c]: + return False + + ### If the cell has been visited, return False + if check[r][c]: + return False + + check[r][c] = True + for dr, dc in DIR: + if backtracking(r + dr, c + dc, n + 1): + return True + check[r][c] = False + + for r in range(ROW): + for c in range(COL): + if board[r][c] == word[0]: + if backtracking(r, c, 0): + return True + + return False From 555e26dec109f6183bedefdfa08313095ef89f2c Mon Sep 17 00:00:00 2001 From: woo Date: Sun, 12 Jul 2026 00:05:13 +0900 Subject: [PATCH 14/14] =?UTF-8?q?fix:=20=EC=BD=94=EB=93=9C=20=EA=B0=80?= =?UTF-8?q?=EB=8F=85=EC=84=B1=20=ED=96=A5=EC=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coin-change/alphaorderly.py | 11 +++-------- maximum-depth-of-binary-tree/alphaorderly.py | 2 +- merge-two-sorted-lists/alphaorderly.py | 15 +++++---------- word-search/alphaorderly.py | 4 ++-- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/coin-change/alphaorderly.py b/coin-change/alphaorderly.py index 50c1187205..dca5339002 100644 --- a/coin-change/alphaorderly.py +++ b/coin-change/alphaorderly.py @@ -14,10 +14,7 @@ def dp(coin: int, left: int) -> int: if left == 0: return 0 - if left < 0: - return LARGE - - if coin >= len(coins): + if left < 0 or coin >= len(coins): return LARGE a = dp(coin, left - coins[coin]) + 1 @@ -65,13 +62,11 @@ def coinChange(self, coins: List[int], amount: int) -> int: class Solution: def coinChange(self, coins: List[int], amount: int) -> int: N = len(coins) - dp = [float('inf')] * (amount + 1) + dp = [float("inf")] * (amount + 1) dp[0] = 0 for c in range(N): for a in range(coins[c], amount + 1): dp[a] = min(dp[a], dp[a - coins[c]] + 1) - ans = dp[-1] - - return ans if ans != float('inf') else -1 + return dp[-1] if dp[-1] != float("inf") else -1 diff --git a/maximum-depth-of-binary-tree/alphaorderly.py b/maximum-depth-of-binary-tree/alphaorderly.py index c62ed54197..d3e57b3354 100644 --- a/maximum-depth-of-binary-tree/alphaorderly.py +++ b/maximum-depth-of-binary-tree/alphaorderly.py @@ -8,7 +8,7 @@ Time Complexity: O(N) Space Complexity: O(N) - Recursive stack space -### Recursive Solution ### +### Recursive Solution ( DFS ) ### 1. If the root is None, return 0 2. Return the maximum of the depth of the left and right subtrees + 1 diff --git a/merge-two-sorted-lists/alphaorderly.py b/merge-two-sorted-lists/alphaorderly.py index 49cca44b58..0f4655fc63 100644 --- a/merge-two-sorted-lists/alphaorderly.py +++ b/merge-two-sorted-lists/alphaorderly.py @@ -19,7 +19,7 @@ def mergeTwoLists( self, list1: Optional[ListNode], list2: Optional[ListNode] ) -> Optional[ListNode]: head = ListNode() - return_node = head + node = head while list1 and list2: if list1.val > list2.val: @@ -31,12 +31,9 @@ def mergeTwoLists( head = head.next - if list1: - head.next = list1 - elif list2: - head.next = list2 + head.next = list1 or list2 - return return_node.next + return node.next """ Time Complexity: O(N) @@ -49,10 +46,8 @@ def mergeTwoLists( """ class Solution: def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: - if not list1: - return list2 - elif not list2: - return list1 + if not list1 or not list2: + return list1 or list2 if list1.val > list2.val: list2.next = self.mergeTwoLists(list1, list2.next) diff --git a/word-search/alphaorderly.py b/word-search/alphaorderly.py index d24b070607..1b2b60d689 100644 --- a/word-search/alphaorderly.py +++ b/word-search/alphaorderly.py @@ -103,7 +103,7 @@ def exist(self, board: List[List[str]], word: str) -> bool: ### Prevent overlapping check = [[False] * COL for _ in range(ROW)] - ### Define the four + ### Define the four possible directions DIR = [ [-1, 0], [1, 0], @@ -111,7 +111,7 @@ def exist(self, board: List[List[str]], word: str) -> bool: [0, 1] ] - ### helper function to check bound + ### Helper function to check bound def bound(r: int, c: int) -> bool: return 0 <= r < ROW and 0 <= c < COL