diff --git a/3sum/liza0525.py b/3sum/liza0525.py new file mode 100644 index 000000000..699244d5d --- /dev/null +++ b/3sum/liza0525.py @@ -0,0 +1,38 @@ +class Solution: + # 해당 문제는 two point 알고리즘을 사용한다. 이 때 '정렬'을 해야 알고리즘을 정확하게 적용할 수 있다. + # 기준 값을 하나 정한 후, 그 값의 다음 인덱스부터 양 끝에 포인터를 두고 세 수의 합을 확인한다. + # 만약 수가 0보다 작으면, 더 큰 수를 더해야 하므로 작은 값 쪽 인덱스를 하나 올리고 + # 0보다 크면, 더 작은 수를 더해야 하므로 큰 쪽 값의 인덱스를 낮춘다. + def threeSum(self, nums: List[int]) -> List[List[int]]: + # nums를 정렬한 후 + nums.sort() + results = set() + + for i in range(len(nums) - 2): + if nums[i] > 0: + # 정렬을 한 후의 가장 작은 수(i가 0일 때의 value)가 0보다 크다면, + # 리스트 내 모든 수가 0보다 크기 때문에 합이 0이 될 수 없으므로 만족하는 답이 없으니 break + break + + if i > 0 and nums[i] == nums[i - 1]: + # 이전 인덱스의 값과 동일한 값이라면 동일한 계산을 반복한 것이므로 + # 중복 계산을 피하기 위해 넘어간다. + continue + + # i 인덱스를 기준으로 오른쪽으로 포인터 설정 + left, right = i + 1, len(nums) - 1 + + while left < right: + result = nums[i] + nums[left] + nums[right] + if result < 0: + # 합이 0보다 작으면 왼쪽 인덱스를 올린다 + left += 1 + elif result > 0: + # 합이 0보다 크면 오른쪽 인덱스를 내린다 + right -= 1 + else: # result == 0 + # 합이 0이면 답이 되므로 results에 추가하고 + # 포인터들을 조정한다. + results.add((nums[i], nums[left], nums[right])) + left, right = left + 1, right - 1 + return list(results) diff --git a/climbing-stairs/liza0525.py b/climbing-stairs/liza0525.py new file mode 100644 index 000000000..2086c75b7 --- /dev/null +++ b/climbing-stairs/liza0525.py @@ -0,0 +1,17 @@ +class Solution: + # n번째 계단에 오를 수 있는 방법 수는 (n - 1번째 계단에 오르는 방법 수) + (n - 2번째 계단에 오르는 방법 수)와 같다. + # 이는 피보나치 수열 공식에 기반하며, 피보나치 수열 상 n번째 오는 수가 곧 답이 된다. + def climbStairs(self, n: int) -> int: + memo = [1, 1, 2] + + def fibonacci(step): + if step > n: + return + + ways = memo[step - 1] + memo[step - 2] + memo.append(ways) + fibonacci(step + 1) + + fibonacci(3) + + return memo[n] diff --git a/product-of-array-except-self/liza0525.py b/product-of-array-except-self/liza0525.py new file mode 100644 index 000000000..ab8e59c25 --- /dev/null +++ b/product-of-array-except-self/liza0525.py @@ -0,0 +1,22 @@ +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + # 자기 자신을 제외한 모든 인덱스의 곱을 곱하는 건, 자기 자신 기준 왼쪽 인덱스들의 곱과 오른쪽 인덱스들의 곱을 최종적으로 곱한 것과 동일하다. + # answer[i]은 (i 기준 왼쪽 인덱스 값들의 누적 곱) * (i 기준 오른쪽 인덱스 값들의 누적 곱) + answers = [1 for _ in range(len(nums))] + + # 여기서 before_total_prod는 인덱스 i 기준 왼쪽 인덱스들의 누적 곱 + # 즉, before_total_prod = nums[1] * num[2] * ... * num[i - 2] * num[i - 1] + before_total_prod = 1 + for i in range(1, len(nums)): + before_total_prod *= nums[i - 1] + answers[i] *= before_total_prod + + # 여기서 after_total_prod는 인덱스 i 기준 오른쪽 인덱스들의 누적 곱 + # 즉, after_total_prod = nums[n - 1] * num[n - 2] * ... * num[i + 2] * num[i + 1] + # (n은 리스트 nums 의 길이, 구현은 n - 1 인덱스부터 거꾸로 계산) + after_total_prod = 1 + for i in range(len(nums) - 2, -1, -1): + after_total_prod *= nums[i + 1] + answers[i] *= after_total_prod + + return answers diff --git a/valid-anagram/liza0525.py b/valid-anagram/liza0525.py new file mode 100644 index 000000000..f86a319c6 --- /dev/null +++ b/valid-anagram/liza0525.py @@ -0,0 +1,25 @@ +from collections import defaultdict + + +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + # 1. s를 구성하고 있는 각 알파벳과 그 알파벳이 존재하는 개수를 세기 위해 + # defaultdict로 dictionary 만들어준다. + alphabet_cnt_dict = defaultdict(int) + + # 2. s의 알파벳을 탐색하면서 alphabet_cnt_dict에서 count(value)를 하나씩 증가 + # 예시: anagram의 경우, {"a": 3, "n": 1, "g": 1, "m": 1, "r": 1}이 최종 값이 됨 + for ss in s: + alphabet_cnt_dict[ss] += 1 + + # 3. t의 알파벳을 탐색하면서 alphabet_cnt_dict에서 count(value)를 하나씩 감소 + # 예시: anagram의 아나그램인 경우, {"a": 0, "n": 0, "g": 0, "m": 0, "r": 0}이 최종 값이 됨 + for tt in t: + alphabet_cnt_dict[tt] -= 1 + + # 4. s와 t가 서로 아나그램이었다면, 구성했던 모든 알파벳에 대해 count 값이 0으로 변경되어 있어야 함 + # 그렇지 않으면(양수 또는 음수 값이 존재하면) 아나그램이라고 할 수 없다. + for cnt in alphabet_cnt_dict.values(): + if cnt != 0: + return False + return True diff --git a/validate-binary-search-tree/liza0525.py b/validate-binary-search-tree/liza0525.py new file mode 100644 index 000000000..4967242e2 --- /dev/null +++ b/validate-binary-search-tree/liza0525.py @@ -0,0 +1,22 @@ +class Solution: + # 중위 순회를 한 결과를 리스트에 저장한 후, 그 결과 리스트 내 value들이 정렬이 되어 있는지 확인 + def isValidBST(self, root: Optional[TreeNode]) -> bool: + inorder_result_list = [] + + def inorder_tree(tree_node): + if tree_node.left: + inorder_tree(tree_node.left) + + inorder_result_list.append(tree_node.val) + + if tree_node.right: + inorder_tree(tree_node.right) + + inorder_tree(root) + + for i in range(len(inorder_result_list) - 1): + # i + 1 인덱스 값보다 i + 1 인덱스의 값이 커야 한다. 아니면 False + if inorder_result_list[i] >= inorder_result_list[i + 1]: + return False + + return True