From c0f204e923ecaabc7a4163fa0a8fcc7f65b8c47e Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Mon, 7 Apr 2025 20:25:35 +0900 Subject: [PATCH 1/7] feat: add Week 02 problems --- 3sum/shinsj4653.py | 13 +++++++++++++ climbing-stairs/shinsj4653.py | 13 +++++++++++++ product-of-array-except-self/shinsj4653.py | 14 ++++++++++++++ valid-anagram/shinsj4653.py | 14 ++++++++++++++ validate-binary-search-tree/shinsj4653.py | 14 ++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 3sum/shinsj4653.py create mode 100644 climbing-stairs/shinsj4653.py create mode 100644 product-of-array-except-self/shinsj4653.py create mode 100644 valid-anagram/shinsj4653.py create mode 100644 validate-binary-search-tree/shinsj4653.py diff --git a/3sum/shinsj4653.py b/3sum/shinsj4653.py new file mode 100644 index 000000000..f7411dc68 --- /dev/null +++ b/3sum/shinsj4653.py @@ -0,0 +1,13 @@ +""" +Inputs: + +Outputs: + +Constraints: + +Time Complexity: + +Space Complexity: + +""" + diff --git a/climbing-stairs/shinsj4653.py b/climbing-stairs/shinsj4653.py new file mode 100644 index 000000000..f7411dc68 --- /dev/null +++ b/climbing-stairs/shinsj4653.py @@ -0,0 +1,13 @@ +""" +Inputs: + +Outputs: + +Constraints: + +Time Complexity: + +Space Complexity: + +""" + diff --git a/product-of-array-except-self/shinsj4653.py b/product-of-array-except-self/shinsj4653.py new file mode 100644 index 000000000..d34e05c19 --- /dev/null +++ b/product-of-array-except-self/shinsj4653.py @@ -0,0 +1,14 @@ +""" +Inputs: + +Outputs: + +Constraints: + +Time Complexity: + +Space Complexity: + +""" + + diff --git a/valid-anagram/shinsj4653.py b/valid-anagram/shinsj4653.py new file mode 100644 index 000000000..d34e05c19 --- /dev/null +++ b/valid-anagram/shinsj4653.py @@ -0,0 +1,14 @@ +""" +Inputs: + +Outputs: + +Constraints: + +Time Complexity: + +Space Complexity: + +""" + + diff --git a/validate-binary-search-tree/shinsj4653.py b/validate-binary-search-tree/shinsj4653.py new file mode 100644 index 000000000..d34e05c19 --- /dev/null +++ b/validate-binary-search-tree/shinsj4653.py @@ -0,0 +1,14 @@ +""" +Inputs: + +Outputs: + +Constraints: + +Time Complexity: + +Space Complexity: + +""" + + From 110fff442b26d845d88a9c87bd9e3ab49d498efe Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Wed, 9 Apr 2025 01:42:23 +0900 Subject: [PATCH 2/7] feat: add "Valid Anagram" solution --- valid-anagram/shinsj4653.py | 69 ++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/valid-anagram/shinsj4653.py b/valid-anagram/shinsj4653.py index d34e05c19..21696faab 100644 --- a/valid-anagram/shinsj4653.py +++ b/valid-anagram/shinsj4653.py @@ -1,14 +1,75 @@ """ -Inputs: +Inputs: two strings : s, t -Outputs: +Outputs: t 가 s의 anagram인지에 대한 여부 Constraints: -Time Complexity: +1 <= s.length, t.length <= 5 * 10^4 +s and t consist of lowercase English letters. -Space Complexity: +Time Complexity: O(n) + +각 문자들의 등장 횟수만 같으면 되지 않나? + +s의 Counter 생성 +t의 Counter 생성 + +t Counter의 keys() 돌면서, +해당 값이 s Counter 배열 key에 있는지, 그리고 그 key의 value값이 서로 같은지 체크 + +Space Complexity: O(n) """ +# 첫 코드 + +from collections import defaultdict + + +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + s_dict, t_dict = defaultdict(int), defaultdict(int) + + for ch in s: + s_dict[ch] += 1 + + for ch in t: + t_dict[ch] += 1 + + for key in t_dict.keys(): + if key not in t_dict or t_dict[key] != s_dict[key]: + return False + + return True + +# 반례 발생 + +# s = "ab", t = "a" +# 어느 한 문자열을 기준으로 세면 안되는 것 같다 +# 두 count 사전을 모두 돌아야할듯. t keys()를 기준으로만 돌면 true가 나와버림. 답은 false인데 + + +from collections import defaultdict + + +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + s_dict, t_dict = defaultdict(int), defaultdict(int) + + for ch in s: + s_dict[ch] += 1 + + for ch in t: + t_dict[ch] += 1 + + for key in t_dict.keys(): + if key not in s_dict or t_dict[key] != s_dict[key]: + return False + + for key in s_dict.keys(): + if key not in t_dict or t_dict[key] != s_dict[key]: + return False + + return True From 4d1ba6d20f6c652d6b405bf34f51c0c8073261f6 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Wed, 9 Apr 2025 20:54:27 +0900 Subject: [PATCH 3/7] feat: add "Climbing Stairs" solution --- climbing-stairs/shinsj4653.py | 93 +++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/climbing-stairs/shinsj4653.py b/climbing-stairs/shinsj4653.py index f7411dc68..7f7b41817 100644 --- a/climbing-stairs/shinsj4653.py +++ b/climbing-stairs/shinsj4653.py @@ -1,13 +1,96 @@ """ -Inputs: +계단 오르기 +맨 꼭대기 가는데 n steps만큼 걸림 -Outputs: +매번 올라가는데 1 or 2 계단 오르기 가능! -Constraints: +Inputs: n -Time Complexity: +Outputs: how many distinct ways to get to the top? -Space Complexity: +Constraints: 1 <= n <= 45 + +Time Complexity: O(2^n) ? + +계단 오르는 방법 중, 중복되지 않는 모든 가지 수 구하기 +우선 완탐으로 해보고, 그 다음 최적부분구조 할 수 있는지 체크 + +n = 2 + +1 1 -> dp[1] +2 0 -> dp + +2 dp(n - 2) + dp(n - 1) + 1 + +n = 3 +2 1 +1 1 1 => dp[2] 값 + +1 2 => 여기선 dp[2] 로 가면 안됨! + +1 2 +1 1 1 => dp[2] 값 + +2 1 => 이건 dp[1] 값 + + +n = 4 +1 3 => dp[3] +2 2 => dp[2] + +n = 5 +2 2 1 +2 1 2 +1 2 2 + +n = 6 + +5 1 +4 2 + +n = 7 + +6 1 +5 4 +4 3 + +특정 수를 구성하는 1과 2의 배열 가짓수들이 정해져있음!! + +한 호출마다 뻗어지는 가짓수, 즉 호출수를 모르겠어서 시간복잡도 모르겠음 + +점화식을 어떻게 세우지? + +3 +1 2 + +기저조건또 헷갈... n 3 // 2 + 1 + +Space Complexity: O(n) +dp 배열 n만큼의 크기 지님 """ + +class Solution: + def climbStairs(self, n: int) -> int: + + if n == 1: + return 1 + + dp = [0] * (n + 1) + dp[0] = 1 + dp[1] = 1 + + def climb(n): + + if dp[n]: + return dp[n] + + else: + dp[n] += climb(n - 1) + climb(n - 2) + return dp[n] + + return climb(n) + +# sol = Solution() +# sol.climbStairs(3) From b2ffe7920236f89bf1fae5d162bc304b31f3bd9b Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Wed, 9 Apr 2025 22:09:37 +0900 Subject: [PATCH 4/7] feat: add "Product of Array Except Self" solution --- climbing-stairs/shinsj4653.py | 10 +++- product-of-array-except-self/shinsj4653.py | 67 ++++++++++++++++++++-- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/climbing-stairs/shinsj4653.py b/climbing-stairs/shinsj4653.py index 7f7b41817..1d815f8a1 100644 --- a/climbing-stairs/shinsj4653.py +++ b/climbing-stairs/shinsj4653.py @@ -10,7 +10,7 @@ Constraints: 1 <= n <= 45 -Time Complexity: O(2^n) ? +Time Complexity: O(2^n) 계단 오르는 방법 중, 중복되지 않는 모든 가지 수 구하기 우선 완탐으로 해보고, 그 다음 최적부분구조 할 수 있는지 체크 @@ -65,6 +65,14 @@ 기저조건또 헷갈... n 3 // 2 + 1 +하지만, 도식화해보니 +결국 dp(n) = dp(n - 1) + dp(n - 2) + +1 2 +1 1 1 => dp[2] 값 + +2 1 => 이건 dp[1] 값 + Space Complexity: O(n) dp 배열 n만큼의 크기 지님 diff --git a/product-of-array-except-self/shinsj4653.py b/product-of-array-except-self/shinsj4653.py index d34e05c19..bbc328c34 100644 --- a/product-of-array-except-self/shinsj4653.py +++ b/product-of-array-except-self/shinsj4653.py @@ -1,14 +1,71 @@ """ -Inputs: +Inputs: 정수형 배열 nums -Outputs: +Outputs: 정수형 배열 answer -Constraints: +Constraints: 2 <= nums.length <= 10^5 +-30 <= nums[i] <= 30 +The input is generated such that answer[i] is guaranteed to fit in a 32-bit integer. -Time Complexity: +Time Complexity: 반드시 o(n) -Space Complexity: +answer의 각 원소는 본인을 제외한 나머지 원소들 곱한 결과 + +나눗셈 연산도 불가능 +사전? +1 2 3 4 +2 4 6 8 +6 12 18 24 +24 48 72 96 + +dict[0] : +dict[1] : +dict[2] : +dict[3] : + +스택?? push, pop 하는데 o(1) 걸림 + +(1,0) (2,1) (3,2) (4,3) + +스택에서 뺀 다음, 다시 넣으면 while st에 갇히지 않나? + +# 풀이 본 이후 + +nums 1 2 3 4 + +1 1 1 1 + +1 1 2 6 : 기준 idx 전까지의 곱 + +24 12 4 1 : 기준 idx 후까지의 곱 + +=> 더 개선된 풀이: 누적곱을 덮어씌우는 방법 + +6 +24 12 8 6 + +24 + + +Space Complexity: O(1) +product 배열에 곱 결과를 덮어씌워도 무방 """ +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + + products = [1 for _ in range(len(nums))] + + before = 1 + for i in range(len(nums) - 1): + before *= nums[i] + products[i + 1] *= before + + after = 1 + for i in range(len(nums) - 1, 0, -1): + after *= nums[i] + products[i - 1] *= after + + return products \ No newline at end of file From e537bec3b195fbc34f73153e0611d29b39d915a4 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Wed, 9 Apr 2025 22:09:58 +0900 Subject: [PATCH 5/7] fix: add lint to "Product of Array Except Self" solution --- product-of-array-except-self/shinsj4653.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product-of-array-except-self/shinsj4653.py b/product-of-array-except-self/shinsj4653.py index bbc328c34..d7e7426a0 100644 --- a/product-of-array-except-self/shinsj4653.py +++ b/product-of-array-except-self/shinsj4653.py @@ -68,4 +68,4 @@ def productExceptSelf(self, nums: List[int]) -> List[int]: after *= nums[i] products[i - 1] *= after - return products \ No newline at end of file + return products From d86d2aff6a7d1d3589409dff466a69de1fa6e23b Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 12 Apr 2025 20:40:16 +0900 Subject: [PATCH 6/7] feat: add "3Sum" solution --- 3sum/shinsj4653.py | 110 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 4 deletions(-) diff --git a/3sum/shinsj4653.py b/3sum/shinsj4653.py index f7411dc68..9c275cb66 100644 --- a/3sum/shinsj4653.py +++ b/3sum/shinsj4653.py @@ -1,13 +1,115 @@ """ -Inputs: +Inputs: 정수 배열 nums -Outputs: +Outputs: triplet 모음 배열 (중복 요소 X) -Constraints: +Constraints: 3 < = nums.length <= 3 * 10^3 +-10^5 <= nums[i] <= 10^5 Time Complexity: -Space Complexity: +각 수들의 위치 다르면서, 합이 0이 되는 조합들의 모음 결과 +n^3 은 안됨 +하지만 가능한 모든 조합 구하기를 효율화 시키면 될듯? + +x 0 1 2 3 4 5 +0 [_,-1,0,1,-2,-5] +1 [_,_,1,2,-1,-4] +2 [_,_,_, +3 +4 +5 + +n^2 + + + +0 [1 2] +0 [1 3] +0 [1 4] +0 [1 5] + +0 1 [2 3] +0 1 [2 4] +0 1 [2 5] + +0 1 2[3 4] +0 1 2[3 5] + +0 1 2 3 [4 5] + +우선 대괄호 안 두 수 합 사전 만들고, +keys() 순회하며, +key = a, b -> a보다 작은 수 for문 돌며 합 구하기? +-> 그럼 시간복잡도 : O(n^3 보다 살짝 작은??) + +하지만 이 풀이로는 중복 후보가 나옴.. + + +Space Complexity: O(n^2) + +대괄호 내 두 수 조합 만큼의 크기가 사전 크기 + +# 1차 제출 코드 + +from collections import defaultdict + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + n = len(nums) + v = defaultdict(int) + ret = [] + memo = set() + + for i in range(1, n): + for j in range(i + 1, n): + v[(i, j)] = nums[i] + nums[j] + + print(v) + for key in v.keys(): + a, b = key + print('key: a, b', a, b) + + for i in range(a): + if nums[i] + v[key] == 0 and \ + not (nums[i] in memo and nums[a] in memo and nums[b] in memo): + print('sum zero!') + memo.add(nums[i]) + memo.add(nums[a]) + memo.add(nums[b]) + ret.append([nums[i], nums[a], nums[b]]) + + + + return ret + +테스트 케이스만 정답.. +nums = +[-1,0,1,2,-1,-4,-2,-3,3,0,4] 인 경우는 오답 + +[회고] +완탐, dp로 해봐도 안 풀리면 투 포인터 생각해보기! """ +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + tuples = set() + nums.sort() + + for i in range(len(nums) - 2): + left, right = i + 1, len(nums) - 1 + + while left < right: + three_sum = nums[i] + nums[left] + nums[right] + if three_sum < 0: + left += 1 + elif three_sum > 0: + right -= 1 + else : + tuples.add((nums[i], nums[left], nums[right])) + left += 1 + right -= 1 + + return list(tuples) + From 86e4ca9bfa7facce5a34f7ea9d0b931e389c5354 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 12 Apr 2025 22:40:51 +0900 Subject: [PATCH 7/7] feat: add "validate-binary-search-tree" solution --- validate-binary-search-tree/shinsj4653.py | 97 +++++++++++++++++++++-- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/validate-binary-search-tree/shinsj4653.py b/validate-binary-search-tree/shinsj4653.py index d34e05c19..070c63a0a 100644 --- a/validate-binary-search-tree/shinsj4653.py +++ b/validate-binary-search-tree/shinsj4653.py @@ -1,14 +1,101 @@ """ -Inputs: +[문제풀이] +# Inputs +TreeNode 클래스 객체 -Outputs: +# Outputs +valid 이진 탐색 트리인지에 대한 여부 -Constraints: +# Constraints +The number of nodes in the tree is in the range [1, 104]. +-2^31 <= Node.val <= 2^31 - 1 -Time Complexity: +# Ideas +root 배열 길이 기준으로 풀려고 했지만, root는 배열이 아닌 TreeNode 클래스의 객체이다. +1. bfs로 구현해보기 +트리 높이 기준으로 퍼지면서 탐색하는 모양이라 bfs 선택 + +cur = root +q.append(cur) + +while not q: + cur_node = q.popleft() + if cur_node == null: + continue + + if cur_node.right != null and (cur_node.left.val > cur_node.val or cur_node.right.val < cur_node.val): + return False + + else: + q.append(cur_node.left) + +먼가 조건문이 길어지는 것 같아 효율적인 풀이는 아닌 것 같지만..일단 시도! + +n이 node 개수라면 +Time: O(n), Space: O(n) + +from collections import deque + +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + q = deque([]) + q.append(root) + + while q: + cur_node = q.popleft() + if cur_node is None: + continue + + if cur_node.left is not None and cur_node.left.val >= cur_node.val: + return False + + elif cur_node.right is not None and cur_node.right.val <= cur_node.val: + return False + + else: + q.append(cur_node.left) + q.append(cur_node.right) + + return True + +- 반례 발생 +root = +[5,4,6,null,null,3,7] + +왜 BST가 아닌지 이해가 안간다.. +-> 3이 5보다 작아서 그렇다 +루트 기준 오른쪽은 자식 값들도 무조건 작아야한다. +그럼 한 단계 위의 값만 보면 안된다는 건데, 탐색 방법 바꿔야 할 것 같다 + +2. 재귀로 돌면서, 이 값보다는 커야한다는 배열을 인자로 함께 넘겨주기? +하지만, 어느 dfs에서 배열 원소들보다 본인 값이 커야하는지, 작야하는지 모름!! + +결국 풀이 참고 + +[회고] -Space Complexity: """ +# 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 +from collections import deque + +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + ret = True + + def dfs(node, low, high): + if not node: + return True + + if not (low < node.val < high): + return False + + return dfs(node.left, low, node.val) and dfs(node.right, node.val, high) + return dfs(root, float("-inf"), float("inf"))