diff --git a/3sum/Chaedie.py b/3sum/Chaedie.py new file mode 100644 index 000000000..e22880c8a --- /dev/null +++ b/3sum/Chaedie.py @@ -0,0 +1,59 @@ +""" +첫번째 풀이 -> 달레의 코드 풀이 +1) sort와 two pointer를 활용한 풀이 +2) has_set 을 활용한 중복 제거 + +두번째 풀이 -> Neetcode 풀이 +1) sort와 two pointer를 활용한 풀이 +2) while loop 를 활용한 중복 제거 + +Time: O(n^2) = O(n) * O(n) +Space: O(n) +""" + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + nums.sort() + res = set() + n = len(nums) + + for i in range(n): + l, r = i + 1, n - 1 + while l < r: + summ = nums[i] + nums[l] + nums[r] + if summ < 0: + l += 1 + elif summ > 0: + r -= 1 + else: + res.add((nums[i], nums[l], nums[r])) + l += 1 + return list(res) + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + nums.sort() + res = [] + n = len(nums) + + for i in range(n): + l, r = i + 1, n - 1 + + if i > 0 and nums[i] == nums[i - 1]: + continue + + while l < r: + summ = nums[i] + nums[l] + nums[r] + if summ < 0: + l += 1 + elif summ > 0: + r -= 1 + else: + res.append([nums[i], nums[l], nums[r]]) + l += 1 + while nums[l] == nums[l - 1] and l < r: + l += 1 + + return res diff --git a/climbing-stairs/Chaedie.py b/climbing-stairs/Chaedie.py new file mode 100644 index 000000000..adf087064 --- /dev/null +++ b/climbing-stairs/Chaedie.py @@ -0,0 +1,39 @@ +''' +solution: + # dp[1] = 1step = 1 + # dp[2] = (1step + 1step) + 2step = 2 + # dp[3] = (dp[3 - 1] + 1step) + dp[3 - 2] + 2step = 2 + 1 = 3 + # dp[4] = (dp[4 - 1] + 1step) + (dp[4 - 2] + 2tep) = 3 + 2 = 5 + + # dp[n] = (dp[n-1] + 1) + (dp[n-2] + 1) + +time O(n) +space O(n) + +''' + +class Solution: + def climbStairs(self, n: int) -> int: + dp = [0] + dp.append(1) + dp.append(2) + + for i in range(3, n+1): + dp.append(dp[i-1] + dp[i-2]) + return dp[n] + +''' +solution2: + 위 솔루션에서 공간 복잡도 최적화 + +time O(n) +space O(1) +''' +class Solution: + def climbStairs(self, n: int) -> int: + pt1, pt2 = 1,1 + for i in range(2, n+1): + temp = pt2 + pt2 = pt1 + pt2 + pt1 = temp + return pt2 diff --git a/construct-binary-tree-from-preorder-and-inorder-traversal/Chaedie.py b/construct-binary-tree-from-preorder-and-inorder-traversal/Chaedie.py new file mode 100644 index 000000000..8587dd26a --- /dev/null +++ b/construct-binary-tree-from-preorder-and-inorder-traversal/Chaedie.py @@ -0,0 +1,57 @@ +# 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 + +""" +1) preorder 의 경우 젤 첫번째 노드가 최상단 노드라는 보장이 있음 +2) inorder 의 경우 preorder 에서의 첫번째 node 를 기준으로 왼쪽이 left 노드, 오른찍이 right 노드라는 보장이 있음 +3) preorder 에서 left, right의 갯수는 inorder에서 찾은 root node 의 인덱스 를 활용할 수 있음 + +Time: O(n^2) +Space: O(n^2) +""" + + +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + if not preorder or not inorder: + return None + + newNode = TreeNode() + newNode.val = preorder[0] + mid = inorder.index(preorder[0]) + newNode.left = self.buildTree(preorder[1 : mid + 1], inorder[:mid]) + newNode.right = self.buildTree(preorder[mid + 1 :], inorder[mid + 1 :]) + + return newNode + +''' +알고달레 참고해서 최적화 진행했습니다. +1) 시간복잡도 최적화: dictionary 를 활용해 mid 를 찾는 index 메서드 제거 +2) 공간복잡도 최적화: preorder, inorder 배열을 넘기는것이 아닌 index 만 넘김 + +Time: O(n) +Space: O(n) + +''' + +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + indices = { val: idx for idx, val in enumerate(inorder) } + pre_iter = iter(preorder) + + def dfs(start, end): + if start > end: + return None + + val = next(pre_iter) + mid = indices[val] + + left = dfs(start, mid - 1) + right = dfs(mid + 1, end) + return TreeNode(val, left, right) + + return dfs(0, len(inorder) - 1) diff --git a/decode-ways/Chaedie.py b/decode-ways/Chaedie.py new file mode 100644 index 000000000..19d0afab4 --- /dev/null +++ b/decode-ways/Chaedie.py @@ -0,0 +1,57 @@ +""" +dp 문제는 아직 어색해서 직접 풀진 못했습니다. +""" + +""" +재귀와 dp hash_map 을 활용한 캐싱 전략 +Time: O(n) +Space: O(n) = O(n) + O(n) +""" + + +class Solution: + def numDecodings(self, s: str) -> int: + dp = {len(s): 1} + + def dfs(i): + if i in dp: + return dp[i] + if s[i] == "0": + return 0 + + # 한자리 숫자 + res = dfs(i + 1) + + # 두자리 숫자 + if i + 1 < len(s) and ( + s[i] == "1" or s[i] == "2" and s[i + 1] in "0123456" + ): + res += dfs(i + 2) + dp[i] = res + return res + + return dfs(0) + + +""" +iterative dp +Time: O(n) +Space: O(n) +""" + + +class Solution: + def numDecodings(self, s: str) -> int: + dp = {len(s): 1} + + for i in range(len(s) - 1, -1, -1): + if s[i] == "0": + dp[i] = 0 + else: + dp[i] = dp[i + 1] + + if i + 1 < len(s) and ( + s[i] == "1" or s[i] == "2" and s[i + 1] in "0123456" + ): + dp[i] += dp[i + 2] + return dp[0] diff --git a/valid-anagram/Chaedie.py b/valid-anagram/Chaedie.py new file mode 100644 index 000000000..4d5eed1d7 --- /dev/null +++ b/valid-anagram/Chaedie.py @@ -0,0 +1,27 @@ +''' +count a frequency of the character with a hash map +s's character will be added and +t's character will be subtracted + +return True if count's min and max value is not a zero +else return False + +Time O(n) +Space O(n) +''' + +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + count = defaultdict(int) + + if len(t) != len(s): + return False + + for i in range(len(s)): + count[s[i]] += 1 + count[t[i]] -= 1 + + if max(count.values()) == 0: + return True + return False +