diff --git a/contains-duplicate/hu6r1s.py b/contains-duplicate/hu6r1s.py new file mode 100644 index 000000000..ae2f2bd29 --- /dev/null +++ b/contains-duplicate/hu6r1s.py @@ -0,0 +1,12 @@ +from collections import Counter + +class Solution: + # 시간복잡도: O(n) - Counter(nums)는 n번 순회하며 각 원소의 개수를 세고, cnt.items()는 최대 n개의 (key, value) 쌍을 포함하므로 최대 n번 순회 + # 공간복잡도: O(n) - Counter는 입력 배열에 있는 각 고유 원소를 키로 저장하므로 최악의 경우 n개의 키를 저장함 + def containsDuplicate(self, nums: List[int]) -> bool: + cnt = Counter(nums) + for _, v in cnt.items(): + if v >= 2: + return True + else: + return False diff --git a/house-robber/hu6r1s.py b/house-robber/hu6r1s.py new file mode 100644 index 000000000..4bfe9e5cc --- /dev/null +++ b/house-robber/hu6r1s.py @@ -0,0 +1,45 @@ +class Solution: + """ + - 이전 풀이 + [1,2,3,1] + 인덱스 0에서 훔쳤을 때, 인덱스 1은 훔치면 안되므로 nums[0] + F(nums[2:]) + 인덱스 0에서 안훔쳤을 때, 인덱스 1에서 훔쳐야 하므로 F(nums[1:]) + + F[nums] = max(nums[0] + F[nums[2:]], F(nums[1:])) + F[i] = max(nums[i] + F(i+2), F(i+1)) + + + - dp + nums = [1, 2, 3, 1] + 집이 하나일 때는 한 곳만 볼 수 있으니 그 집의 돈을 훔침: dp[0] = nums[0] = 1 + 집이 두 개일 때, 인덱스 0인 곳을 갔다면 dp[0]이 가장 크고, + 가지 않았다면 인덱스 1을 가게 됨. dp[1] = max(dp[0], nums[1]) = max(1, 2) = 2 + 그래서 인덱스 0을 갔을 때와 가지 않았을 때를 고려하여 큰 돈을 가져옴 + 집이 세 개일 때, 인덱스 0을 갔다면 인덱스 2를 가야하고, 인덱스 0을 가지 않았다면 인덱스 1을 감 + 이를 고려하면, 인덱스 0을 갔을 때의 가장 큰 값이 dp[0]이고, 인덱스 2를 가야하니 nums[2]를 더한 값과 + 인덱스 0에 가지 않고 인덱스 1로 갔다면 dp[1]이 가장 크다. + 그래서 dp[2] = max(dp[0] + nums[2], dp[1]) + 집이 네 개일 때, 인덱스 3을 간다면 인덱스 1을 가게 되므로 인덱스 1까지의 dp 값과 인덱스 3의 값을 더한 값과 + 인덱스 3을 가지 않는다면 인덱스 0과 인덱스 2를 가게 된다. + 그렇다면 인덱스 2까지의 값을 비교하여 더 큰 돈을 가져간다. + 그래서 dp[3] = max(dp[1] + nums[3], dp[2])가 된다. + + - TC + - for loop -> O(n) + - SC + - dp 테이블 크기 -> O(n) + """ + 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(dp[0], nums[1]) + + for i in range(2, len(nums)): + dp[i] = max(dp[i-2] + nums[i], dp[i-1]) + + return dp[-1] diff --git a/longest-consecutive-sequence/hu6r1s.py b/longest-consecutive-sequence/hu6r1s.py new file mode 100644 index 000000000..6193f58d7 --- /dev/null +++ b/longest-consecutive-sequence/hu6r1s.py @@ -0,0 +1,31 @@ +class Solution: + """ + nums를 내림차순 sort하고, 차례대로 두 개의 차가 다음 차가 같다면 + 1 + 처음 차는 diff 변수에 저장하고, 진행되면서 diff를 업데이트 + 200, 100, 4, 3, 2, 1 + + 연속된 수열이라고 하여 1 이외의 다른 수가 올 수 있을 것이라고 판단하였지만 차이가 1로 나온다는 것을 확인 + + - TC + - set(nums) -> O(n) + - for -> O(n) + - while -> O(n) + - 전체 -> O(n) + - SC + - num_set -> O(n) + - 다른 변수들 -> O(1) + - 전체 -> O(n) + """ + def longestConsecutive(self, nums: List[int]) -> int: + num_set = set(nums) + longest = 0 + + for num in num_set: + if num - 1 not in num_set: + k = 1 + + while num + k in num_set: + k += 1 + + longest = max(longest, k) + return longest diff --git a/top-k-frequent-elements/hu6r1s.py b/top-k-frequent-elements/hu6r1s.py new file mode 100644 index 000000000..82131cc98 --- /dev/null +++ b/top-k-frequent-elements/hu6r1s.py @@ -0,0 +1,18 @@ +from collections import Counter + +class Solution: + """ + - TC + - Counter(nums): O(n) + - sorted(): O(n log n) + - 슬라이싱 및 리스트 변환: O(k) + - 전체: O(n log n) + - SP + - Counter 및 정렬된 딕셔너리 저장: O(n) + - 반환 리스트: O(k) + - 전체: O(n) + """ + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + count_nums = Counter(nums) + count_nums = dict(sorted(count_nums.items(), reverse=True, key=lambda x: x[1])).keys() + return list(count_nums)[:k] diff --git a/two-sum/hu6r1s.py b/two-sum/hu6r1s.py new file mode 100644 index 000000000..09b97e2be --- /dev/null +++ b/two-sum/hu6r1s.py @@ -0,0 +1,27 @@ +""" + - Time Complexity + - 바깥 for 루프는 n - 1번, 안쪽 루프는 최대 n - i - 1번 실행 + - 전체적으로 O(n^2)의 시간 복잡도를 가짐짐 + + - Space Complexity + - 별도의 자료구조를 사용하지 않음 + - 변수 i, j 그리고 리턴 시 사용하는 [i, j]만 존재 + - 따라서 O(1)의 공간 복잡도를 가짐짐 +""" +""" + class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + for i in range(len(nums)-1): + for j in range(i+1, len(nums)): + if nums[i] + nums[j] == target: + return [i, j] +""" + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + d = {num: idx for idx, num in enumerate(nums)} + + for i, v in enumerate(nums): + idx = target - v + if idx in d and d[idx] != i: + return [i, d[idx]]