From 1c489a31920bc26c017ef3ab24fd496ce2a33296 Mon Sep 17 00:00:00 2001 From: hi-rachel Date: Fri, 1 Aug 2025 21:47:51 +0900 Subject: [PATCH 1/6] valid-anagram sol (py) --- valid-anagram/hi-rachel.py | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 valid-anagram/hi-rachel.py diff --git a/valid-anagram/hi-rachel.py b/valid-anagram/hi-rachel.py new file mode 100644 index 000000000..686e336b1 --- /dev/null +++ b/valid-anagram/hi-rachel.py @@ -0,0 +1,41 @@ +""" +https://leetcode.com/problems/valid-anagram/description/ +두 문자열이 애너그램인지 확인하는 함수를 작성하세요. +애너그램이란 두 문자열이 중복된 알파벳을 같은 개수만큼 포함하고 있는 것을 의미합니다. + +TC: O(n) +SC: O(k), k = 알파벳 개수 +""" + +from collections import defaultdict + +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + def makeMap(s: str): + str_map = defaultdict(int) + for char in s: + str_map[char] += 1 + return str_map + + return makeMap(s) == makeMap(t) + + +""" +정렬 풀이 + +TC: O(nlogn) +SC: O(1) +""" +def isAnagram(s: str, t: str) -> bool: + return sorted(s) == sorted(t) + +""" +Counter 사용 풀이 + +TC: O(n) +SC: O(k) +""" +from collections import Counter + +def isAnagram(s: str, t: str) -> bool: + return Counter(s) == Counter(t) From 82cfd903a62b4e35bcb455ea1673747408bfd18d Mon Sep 17 00:00:00 2001 From: hi-rachel Date: Fri, 1 Aug 2025 21:56:53 +0900 Subject: [PATCH 2/6] climbing-stairs sol (py) --- climbing-stairs/hi-rachel.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 climbing-stairs/hi-rachel.py diff --git a/climbing-stairs/hi-rachel.py b/climbing-stairs/hi-rachel.py new file mode 100644 index 000000000..199691bcb --- /dev/null +++ b/climbing-stairs/hi-rachel.py @@ -0,0 +1,36 @@ +""" +https://leetcode.com/problems/climbing-stairs/description/ + +한 번에 1계단 혹은 2계단 오를 수 있음 +1: 1 +2: 2 +3: 1 + 1 + 1, 1 + 2, 2 + 1 => 3 +4: 1 + 1 + 1 + 1, 1 + 1 + 2, 2 + 1 + 1, 1 + 2 + 1, 2 + 2 => 5 +5: 1 + 1 + 1 + 1 + 1, + 1 + 1 + 1 + 2, + 1 + 1 + 2 + 1 + 1, + 1 + 2 + 1 + 1, + 2 + 1 + 1 + 1, + 2 + 2 + 1, + 2 + 1 + 2, + 1 + 2 + 2, + => 8 + +steps[n] = steps[n - 1] + steps[n - 2] + +TC: O(n) +SC: O(n) +""" + +class Solution: + def climbStairs(self, n: int) -> int: + if n == 1: + return 1 + elif n == 2: + return 2 + steps = [0] * n + steps[0] = 1 + steps[1] = 2 + for i in range(2, n): + steps[i] = steps[i - 2] + steps[i - 1] + return steps[n - 1] From ec12b17a4cde65378408d0e51657cff2ea271c0f Mon Sep 17 00:00:00 2001 From: hi-rachel Date: Fri, 1 Aug 2025 22:23:47 +0900 Subject: [PATCH 3/6] product-of-array-except-self sol (py) --- product-of-array-except-self/hi-rachel.py | 42 +++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 product-of-array-except-self/hi-rachel.py diff --git a/product-of-array-except-self/hi-rachel.py b/product-of-array-except-self/hi-rachel.py new file mode 100644 index 000000000..02a083373 --- /dev/null +++ b/product-of-array-except-self/hi-rachel.py @@ -0,0 +1,42 @@ +""" +https://leetcode.com/problems/product-of-array-except-self/description/ + +문제: 정수 배열 nums가 주어졌을 때, 각 원소를 제외한 나머지 원소들의 곱을 반환하세요. +단, 나누기 연산을 사용하지 말고 O(n) 시간 복잡도로 해결하세요. + +핵심 아이디어: +각 원소를 기준으로: +- 왼쪽에 있는 원소들의 곱 +- 오른쪽에 있는 원소들의 곱 +을 각각 곱해주면, 자기 자신을 제외한 전체 곱이 된다. + +예시: [1, 2, 3, 4] +- 인덱스 0: 왼쪽(없음) × 오른쪽(2×3×4) = 24 +- 인덱스 1: 왼쪽(1) × 오른쪽(3×4) = 12 +- 인덱스 2: 왼쪽(1×2) × 오른쪽(4) = 8 +- 인덱스 3: 왼쪽(1×2×3) × 오른쪽(없음) = 6 + +TC: O(n) - 배열을 두 번 순회 +SC: O(1) - 결과 배열을 제외한 추가 공간 사용하지 않음 +""" + +from typing import List + +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + n = len(nums) + result = [1] * n # 결과 배열 초기화 + + # 1단계: 왼쪽에서 오른쪽으로 순회하며 왼쪽 원소들의 곱 계산 + left_product = 1 + for i in range(n): + result[i] = left_product # 현재 위치에 왼쪽 곱 저장 + left_product *= nums[i] # 다음을 위해 현재 원소 곱하기 + + # 2단계: 오른쪽에서 왼쪽으로 순회하며 오른쪽 원소들의 곱 계산 + right_product = 1 + for i in range(n - 1, -1, -1): + result[i] *= right_product # 기존 왼쪽 곱에 오른쪽 곱 곱하기 + right_product *= nums[i] # 다음을 위해 현재 원소 곱하기 + + return result From dfdc227418b269936fb2217f1bd4ebdc361c94a5 Mon Sep 17 00:00:00 2001 From: hi-rachel Date: Fri, 1 Aug 2025 22:59:52 +0900 Subject: [PATCH 4/6] 3sum sol (py) --- 3sum/hi-rachel.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/3sum/hi-rachel.py b/3sum/hi-rachel.py index 796ba0bb0..af67e5deb 100644 --- a/3sum/hi-rachel.py +++ b/3sum/hi-rachel.py @@ -1,5 +1,64 @@ -# O(n^2) time, O(n) space +""" +https://leetcode.com/problems/3sum/ + +문제 설명: +정렬되지 않은 정수 배열 nums가 주어질 때, +세 수의 합이 0이 되는 모든 유니크한 triplet을 찾는 문제. + +조건: +- 중복 조합은 허용되지 않음. +- 예: [-1, 0, 1]과 [0, -1, 1]은 같은 조합이므로 하나만 포함. + +풀이 전략: +1. 배열을 정렬한다. +2. 첫 번째 수를 고정한 뒤, 나머지 두 수를 투포인터로 탐색한다. + - 합이 0보다 작으면 left를 증가 + - 합이 0보다 크면 right를 감소 + - 합이 0이면 정답에 추가, 중복 방지 처리도 함께 수행 + +TC: O(n^2), 정렬 O(n log n) + 투포인터 O(n^2) +SC: O(1), 출력 공간 result 제외 +""" + +from typing import List + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + nums.sort() + result = [] + + for i in range(len(nums) - 2): + if i > 0 and nums[i] == nums[i - 1]: + continue # 중복 제거 + + left, right = i + 1, len(nums) - 1 + + while left < right: + total = nums[i] + nums[left] + nums[right] + # 조건 만족시 정답에 추가 + if total == 0: + result.append([nums[i], nums[left], nums[right]]) + # 같은 값을 가진 left가 여러 개 있다면, 중복 건너뜀 + while left < right and nums[left] == nums[left + 1]: + left += 1 + # 같은 값을 가진 right가 여러 개 있다면, 중복 건너뜀 + while left < right and nums[right] == nums[right - 1]: + right -= 1 + left += 1 + right -= 1 + # 총합이 0보다 작으면, 더 큰 수가 필요하니까 left를 오른쪽으로 이동 + elif total < 0: + left += 1 + # 총합이 0보다 크면, 더 작은 수가 필요하니까 right를 왼쪽으로 이동 + else: + right -= 1 + return result + + + +# O(n^2) time, O(n) space class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: triplets = set() From cbe8951ce4930b8b45e8ea8676a683e6004069f2 Mon Sep 17 00:00:00 2001 From: hi-rachel Date: Fri, 1 Aug 2025 23:25:06 +0900 Subject: [PATCH 5/6] validate-binary-search-tree sol (py) --- validate-binary-search-tree/hi-rachel.py | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/validate-binary-search-tree/hi-rachel.py b/validate-binary-search-tree/hi-rachel.py index 6a794f096..6512e1355 100644 --- a/validate-binary-search-tree/hi-rachel.py +++ b/validate-binary-search-tree/hi-rachel.py @@ -1,3 +1,73 @@ +""" +모든 왼쪽 서브트리는 현재 노드보다 작아야 하고, +모든 오른쪽 서브트리는 현재 노드보다 커야 한다. + +이걸 위해서 범위(min/max)를 재귀로 내려보내야 한다. + +TC: O(n), 모든 노드 1번씩 탐색 +SC: O(h), 재귀 호출 스택, h는 트리 높이 +""" + +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: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + def validate(node, low, high): + if not node: + return True # 비어있는 노드는 BST + # 현재 노드가 범위 밖이면 BST 조건 위배 + if not (low < node.val < high): + return False + # 왼쪽은 최대값을 현재 노드보다 작게 제한 + # 오른쪽은 최소값을 현재 노드보다 크게 제한 + return (validate(node.left, low, node.val) and + validate(node.right, node.val, high)) + + return validate(root, float('-inf'), float('inf')) + + +""" +스택 풀이 + +- BST에서 중위 순회하면 항상 오름차순이어야 한다는 성질을 이용한 방법 +- 중위 순회: 왼쪽 → 현재 노드 → 오른쪽 +- BST는 중위 순회 시 값이 항상 증가해야 하므로, (오름차순) + 이전 노드(prev)보다 현재 노드 값이 작거나 같으면 잘못된 BST + +TC: O(n), 모든 노드 1번씩 탐색 +SC: O(h), 최대 스택 깊이 = 트리 높이 +""" + +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + stack = [] + prev = None # 이전 중위 순회 값 + + while stack or root: + # 왼쪽 끝까지 탐색 + while root: + stack.append(root) + root = root.left + + root = stack.pop() + + # 이전 값보다 작거나 같으면 BST 위반 + if prev is not None and root.val <= prev: + return False + prev = root.val + + # 오른쪽으로 이동 + root = root.right + + return True + + # O(n) time, O(n) space # Definition for a binary tree node. From 8e8234a467f2bda04683fb610b9730fbf5ffa4de Mon Sep 17 00:00:00 2001 From: hi-rachel Date: Fri, 1 Aug 2025 23:46:01 +0900 Subject: [PATCH 6/6] =?UTF-8?q?climbing-stairs=20=EA=B3=B5=EA=B0=84=20?= =?UTF-8?q?=EB=B3=B5=EC=9E=A1=EB=8F=84=20=EC=B5=9C=EC=A0=81=ED=99=94=20sol?= =?UTF-8?q?=20(py)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- climbing-stairs/hi-rachel.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/climbing-stairs/hi-rachel.py b/climbing-stairs/hi-rachel.py index 199691bcb..e750d4ab7 100644 --- a/climbing-stairs/hi-rachel.py +++ b/climbing-stairs/hi-rachel.py @@ -34,3 +34,21 @@ def climbStairs(self, n: int) -> int: for i in range(2, n): steps[i] = steps[i - 2] + steps[i - 1] return steps[n - 1] + +""" +변수 2개로 최적화 +공간 복잡도 O(1) 개선 풀이 +""" +class Solution: + def climbStairs(self, n: int) -> int: + if n == 1: + return 1 + elif n == 2: + return 2 + + prev1 = 1 + prev2 = 2 + + for i in range(2, n): + prev1, prev2 = prev2, prev1 + prev2 + return prev2