diff --git a/contains-duplicate/liza0525.py b/contains-duplicate/liza0525.py new file mode 100644 index 000000000..039550294 --- /dev/null +++ b/contains-duplicate/liza0525.py @@ -0,0 +1,15 @@ +# 시간 복잡도: O(n) +# - for문 하나로 linear 탐색 +# 공간 복잡도: O(n) +# - check_set은 최대 n개만큼 늘어날 수 있음 +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + check_set = set() + for num in nums: + if num in check_set: + # check_set에 이미 있는 경우라면 중복 숫자가 있으므로 True를 return + return True + # check한 숫자는 set에 저장 + check_set.add(num) + # for문 모두를 돌았다면 중복 숫자가 없다는 의미이므로 False를 return + return False diff --git a/house-robber/liza0525.py b/house-robber/liza0525.py new file mode 100644 index 000000000..0ef358aab --- /dev/null +++ b/house-robber/liza0525.py @@ -0,0 +1,31 @@ +# 시간 복잡도: O(n) +# - dfs(start_i)는 start_i마다 한 번만 계산됨 (memoization하기 때문) +# - 가능한 start_i 상태는 0 ~ n-1 이므로 총 n개 +# 공간 복잡도: O(n) +# - memo dictionary가 최대 n개의 결과를 저장 +# - 재귀 DFS 호출 스택 깊이가 최대 n +class Solution: + def rob(self, nums: List[int]) -> int: + houses = len(nums) + memo = {} + + def dfs(start_i): + if start_i in memo: + # memo에 저장된 정보라면 해당 값을 return + return memo[start_i] + + if start_i >= houses: + # start_i가 전체 집 개수(len(nums))를 벗어나면 더이상 계산할 이유가 없으므로 0 return + return 0 + else: + # start_i에서 시작해서 계산한 최대 비용은 + # start_i + 2에서 시작했을 때의 최대 비용 및 nums[start_i]의 비용의 합과, + # start_i + 1에서 시작했을 때의 최대 비용을 + # 비교하여 더 큰 값이 된다. + + # 계산한 start_i에서의 최대 비용은 memo에 저장 + memo[start_i] = max(nums[start_i] + dfs(start_i + 2), dfs(start_i + 1)) + return memo[start_i] + + result = dfs(0) + return result diff --git a/longest-consecutive-sequence/liza0525.py b/longest-consecutive-sequence/liza0525.py new file mode 100644 index 000000000..dfce3a574 --- /dev/null +++ b/longest-consecutive-sequence/liza0525.py @@ -0,0 +1,61 @@ +# 시간 복잡도: O(n) +# - while문이 이중으로 쓰였지만, nums에 있는 각 요소를 한 번 씩만 탐색하는 풀이임(이미 확인한 요소는 pop/remove로 없애기 때문) +# 공간 복잡도: O(n) +# - set 하나만 사용했기 때문에 길이인 n개만큼만 공간 차지 + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + nums = set(nums) + max_length = 1 if nums else 0 # 빈 배열이 들어올 땐 가장 긴 경우는 0밖에 없음 + + while nums: + num = nums.pop() # 기준이 될 num을 하나 가져옴 + length = 1 + left, right = 1, 1 + while num - left in nums: + # 기준 num에서 왼쪽으로 확장 가능한 정도를 계산하여 length를 늘림 + nums.remove(num - left) + length += 1 + left += 1 + while num + right in nums: + # 기준 num에서 오른쪽으로 확장 가능한 정도를 계산하여 length를 늘림 + nums.remove(num + right) + length += 1 + right += 1 + + max_length = max(max_length, length) # 기존에 계산해둔 max_length와 비교하여 업데이트 + + return max_length + + + +# # ** Other trial +# # 시간 복잡도: O(n log n) +# # - sorting을 했기 때문. 문제 통과는 되지만 문제 내 힌트인 O(n)의 시간복잡도를 충족하진 않음 +# # 공간 복잡도: O(n) +# # - nums를 set -> list으로 변환하면서 n개의 개수만큼 저장공간 사용 +# class Solution: +# def longestConsecutive(self, nums: List[int]) -> int: +# nums = list(set(nums)) +# if not nums: +# return 0 + +# if len(nums) == 1: +# return 1 + +# nums.sort() +# max_length = 1 + +# start_i = 0 +# length = 1 +# while start_i < len(nums) - 1 and start_i + length < len(nums): +# length = 1 +# for i in range(start_i, len(nums) - 1): +# if nums[i + 1] == nums[i] + 1: +# length += 1 +# else: +# start_i = i + 1 +# break +# max_length = max(max_length, length) + +# return max_length diff --git a/two-sum/liza0525.py b/two-sum/liza0525.py new file mode 100644 index 000000000..93c152267 --- /dev/null +++ b/two-sum/liza0525.py @@ -0,0 +1,21 @@ +# 시간 복잡도: O(n) +# - nums를 순회하며 dictionary 생성 O(n) +# - nums를 한 번 더 순회하며 target 탐색 O(n) +# 공간 복잡도: O(n) +# - 각 숫자의 index를 저장하는 dictionary idx_map이 최대 n개의 원소를 가짐 + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + # 요소가 어떤 index값을 가지는지 매칭한 dictionary + idx_map = { + el: idx + for idx, el in enumerate(nums) + } + + for idx, num in enumerate(nums): + # target를 만드는, num과 짝이 되는 수를 result_num으로 계산 + result_num = target - num + if result_num in idx_map and idx != idx_map[result_num]: + # 문제의 조건에 맞는 경우에 각 숫자의 index 정보를 early return + # 문제 조건에 무조건 한 가지 경우만 있다고 했기 때문에 early return해도 된다. + return [idx, idx_map[result_num]]