diff --git a/contains-duplicate/hi-rachel.ts b/contains-duplicate/hi-rachel.ts new file mode 100644 index 000000000..d42b54b4c --- /dev/null +++ b/contains-duplicate/hi-rachel.ts @@ -0,0 +1,18 @@ +/** + * 어떤 value든 array에서 2번 나오면 true 반환 + * 다 unique한 값이면 false 반환 + * O(N) time, O(N) space + * */ + +function containsDuplicate(nums: number[]): boolean { + let numMap = new Map(); + + for (let i = 0; i < nums.length; i++) { + if (numMap.has(nums[i])) { + return true; + } else { + numMap.set(nums[i], 1); + } + } + return false; +} diff --git a/house-robber/hi-rachel.py b/house-robber/hi-rachel.py new file mode 100644 index 000000000..3b99750bc --- /dev/null +++ b/house-robber/hi-rachel.py @@ -0,0 +1,42 @@ +# O(n) time, O(n) space +# dp[i]는 i번째 집까지 봤을 때의 최대 누적 금액 + +# 두 가지 선택지를 고려: +# 1. 이 집을 턴다: +# 이전 집은 털 수 없으니 dp[i-2] + nums[i] +# 2. 이 집을 안 턴다: +# 그냥 전 집까지의 최대 금액 유지: dp[i-1] +# 두 가지 선택지 중 큰 걸 선택 +# **dp[i] = max(dp[i-1], dp[i-2] + nums[i])** +# nums 길이가 2인 경우 range(2, 2)는 for문 안 돈다. + +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: return 0 + if len(nums) == 1: return nums[0] + + dp = [0] * len(nums) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + for i in range(2, len(nums)): + dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]) + + return dp[-1] + + +# TS 코드 +# function rob(nums: number[]): number { +# if (nums.length === 0) return 0; +# if (nums.length === 1) return nums[0]; + +# const dp: number[] = new Array(nums.length).fill(0); +# dp[0] = nums[0]; +# dp[1] = Math.max(nums[0], nums[1]); + +# for (let i = 2; i < nums.length; i++) { +# dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); +# } + +# return dp[nums.length - 1]; +# } diff --git a/longest-consecutive-sequence/hi-rachel.py b/longest-consecutive-sequence/hi-rachel.py new file mode 100644 index 000000000..bc6a3265a --- /dev/null +++ b/longest-consecutive-sequence/hi-rachel.py @@ -0,0 +1,121 @@ +# 처음 풀이 +# O(n log n) time, O(n) space + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + if nums == []: + return 0 + + nums.sort() + result = [] + cnt = 1 + + for i in range(len(nums)-1): + if nums[i]+1 == nums[i+1]: + cnt += 1 + elif nums[i] == nums[i+1]: + continue + else: + result.append(cnt) + cnt = 1 + result.append(cnt) + + return max(result) + +# 공간 복잡도 O(1) 개선 풀이 +# result 배열 사용시 최악의 경우 최대 n개의 숫자가 저장되므로 O(n) 공간 사용 +# longest 정수 변수 사용시 상수 공간 사용 + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + if not nums: # pythonic code + return 0 + + nums.sort() + longest = 0 + cnt = 1 + + for i in range(len(nums)-1): + if nums[i]+1 == nums[i+1]: + cnt += 1 + elif nums[i] == nums[i+1]: + continue + else: + longest = max(cnt, longest) + cnt = 1 + longest = max(cnt, longest) + + return longest + +# 시간 복잡도 O(n) 개선 풀이 +# 현재 문제의 요구사항은 시간 복잡도 O(n)이었으므로, 위에 풀이들은 틀렸음 (You must write an algorithm that runs in O(n) time.) +# O(n) time, O(n) space -> 리트 코드 통과 x + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + num_set = set(nums) + longest = 0 + + for num in nums: + if num - 1 in num_set: + continue + cnt = 1 + while num + cnt in num_set: + cnt += 1 + longest = max(cnt, longest) + + return longest + + +# 최종 개선 풀이 +# O(n) time, O(n) space +# 위 풀이에서 한쪽으로 구간을 찾지 않고, 양쪽으로 찾으며 숫자를 집합에서 제거하며 +# 집합에서 원소가 하나도 남지 않을 때까지 하면 가장 긴 구간의 길이를 구할 수 있다. +# 배열의 모든 정수를 set에 저장했으므로 공간 복잡도는 O(n) + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + longest = 0 + num_set = set(nums) + + while num_set: + num = num_set.pop() + left, right = 1, 1 + + while num - left in num_set: + num_set.remove(num - left) + left += 1 + + while num + right in num_set: + num_set.remove(num + right) + right += 1 + longest = max(left + right - 1, longest) + + return longest + +# TS 풀이 +# O(n) time, O(n) space +# JavaScript Set에서 값을 꺼내고자 할때는 **numSet.values().next().value** 사용 + +# function longestConsecutive(nums: number[]): number { +# let numSet = new Set(nums); +# let longest = 0; + +# while (numSet.size !== 0) { +# let num = numSet.values().next().value; +# numSet.delete(num); +# let [left, right] = [1, 1]; + +# while (numSet.has(num - left)) { +# numSet.delete(num - left); +# left += 1; +# } + +# while (numSet.has(num + right)) { +# numSet.delete(num + right); +# right += 1; +# } +# longest = Math.max(left + right - 1, longest); +# } +# return longest; +# }; diff --git a/top-k-frequent-elements/hi-rachel.py b/top-k-frequent-elements/hi-rachel.py new file mode 100644 index 000000000..8d0aac0ca --- /dev/null +++ b/top-k-frequent-elements/hi-rachel.py @@ -0,0 +1,17 @@ +# 가장 자주 등장한 상위 K개의 문자 배열 반환 +# O(n log n) time, O(n) space + +from collections import defaultdict + +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + numdict = defaultdict(int); + + for num in nums: + numdict[num] += 1 + + sort_dict = dict(sorted(numdict.items(), key=lambda item: item[1], reverse=True)) + + keys = list(sort_dict) + + return keys[:k] diff --git a/two-sum/hi-rachel.py b/two-sum/hi-rachel.py new file mode 100644 index 000000000..4b317cdc0 --- /dev/null +++ b/two-sum/hi-rachel.py @@ -0,0 +1,50 @@ +""" +처음 풀이 +O(N^2) time, O(N) space +""" + +# class Solution: +# def twoSum(self, nums: List[int], target: int) -> List[int]: +# result = [] +# for i in range(len(nums)): +# rest = target - nums[i] +# rest_nums = nums[i+1:] +# if rest in rest_nums: +# result.extend([i, rest_nums.index(rest)+i+1]) +# break +# return result + + +""" +개선 코드 +O(N) time, O(N) space +""" + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + indices = {} + + for i, v in enumerate(nums): + diff = target - v + if diff in indices: + j = indices[diff] + return [i, j] + indices[v] = i + +# JS 풀이 +# /** +# * @param {number[]} nums +# * @param {number} target +# * @return {number[]} +# */ +# var twoSum = function(nums, target) { +# let indices = new Map(); + +# for (let i = 0; i < nums.length; i++) { +# diff = target - nums[i]; +# if (indices.has(diff)) { +# return [i, indices.get(diff)]; +# } +# indices.set(nums[i], i); +# } +# };