diff --git a/contains-duplicate/ZetBe.py b/contains-duplicate/ZetBe.py new file mode 100644 index 0000000000..59dae315e1 --- /dev/null +++ b/contains-duplicate/ZetBe.py @@ -0,0 +1,29 @@ +''' +문제: 배열의 중복을 찾는 문제 +풀이: 정렬 후 인접한 원소끼리 비교하여 중복 여부 확인 중복이 없다면 False 반환 + +시간복잡도: O(n log n) +sort()의 시간복잡도는 O(n log n)이고, for문은 O(n)이므로, +전체 시간복잡도는 O(n log n) + +공간복잡도: O(1) +nums.sort()는 제자리 정렬이므로, 추가적인 공간을 사용하지 않는다. +또한 num 변수를 하나만 사용하므로, 전체 공간복잡도는 O(1) + +사용한 자료구조: 리스트 + +만약 파이썬의 딕테이션과 같이 조회 시 O(1)인 자료구조를 사용한다면, +시간복잡도를 O(n)으로 줄일 수 있다. +''' + +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + nums.sort() + num = nums[0] + for i in range(1, len(nums)): + if num == nums[i]: + return True + num = nums[i] + return False + + diff --git a/house-robber/ZetBe.py b/house-robber/ZetBe.py new file mode 100644 index 0000000000..4545b88b34 --- /dev/null +++ b/house-robber/ZetBe.py @@ -0,0 +1,33 @@ +''' +문제: 연속한 집이 아닌 집을 털 때 얻을 수 있는 최대 금액을 구하는 문제 +풀이: 다이나믹 프로그래밍 + 초기 값 설정 후, + dp[i] = max(dp[i-2], dp[i-3]) + nums[i] 점화식 설정 + 한집, 혹은 두집을 건너서 털었을 경우, 둘 중 가장 큰값을 고름 + +시간복잡도: O(n) + 점점 순차적으로 dp 배열을 채워나가므로 O(n) +공간복잡도: O(n) + dp 배열을 하나 생성하므로 O(n) + +사용한 자료구조: 리스트 + +''' + + +class Solution: + def rob(self, nums: List[int]) -> int: + dp = [0 for i in range(len(nums))] + if len(nums) == 1: + return nums[0] + elif len(nums) == 2: + return max(nums[0], nums[1]) + elif len(nums) == 3: + return max(nums[0], nums[1], nums[0]+nums[2]) + + dp[0], dp[1], dp[2] = nums[0], nums[1], nums[0]+nums[2] + + for i in range(3, len(nums)): + dp[i] = max(dp[i-2], dp[i-3]) + nums[i] + return max(dp[len(nums)-1], dp[len(nums)-2]) + diff --git a/longest-consecutive-sequence/ZetBe.py b/longest-consecutive-sequence/ZetBe.py new file mode 100644 index 0000000000..cd8f91185c --- /dev/null +++ b/longest-consecutive-sequence/ZetBe.py @@ -0,0 +1,36 @@ +''' +문제: 배열에서 가장 긴 연속된 수열의 길이를 찾는 문제 +풀이: 딕셔너리의 키값을 기준으로 정렬 후, 연속된 수열의 길이를 계산 + (중복된 값은 딕셔너리로 제거 후 처리) + +시간복잡도: O(k log k + N) (k는 딕셔너리의 키 개수, N은 nums의 길이) +공간복잡도: O(N) (공간의 크기는 nums의 길이에 비례) + +사용한 자료구조: 딕셔너리, 리스트 +''' + + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + d = {} + answ = 1 + if len(nums) > 0: + for i in nums: + if i not in d: + d[i] = 0 + + a = sorted(d.keys()) + now = a[0] + an = 1 + for i in range(1, len(a)): + t = a[i] + if now+1 == t: + an += 1 + else: + an = 1 + now = a[i] + answ = max(answ, an) + + return answ + return 0 + diff --git a/top-k-frequent-elements/ZetBe.py b/top-k-frequent-elements/ZetBe.py new file mode 100644 index 0000000000..58ccd39f32 --- /dev/null +++ b/top-k-frequent-elements/ZetBe.py @@ -0,0 +1,34 @@ +''' +문제: Top K Frequent Elements +nums 배열에서 가장 자주 등장하는 k개의 요소를 반환하라. +풀이: 딕셔너리를 이용하여 각 숫자의 등장 빈도를 저장한 후, + 빈도수를 기준으로 정렬하여 상위 k개의 숫자를 반환한다. + +시간복잡도: O(k log k + n) (n은 nums의 길이, k는 반환할 요소의 개수) + 최악의 경우, O(n log n)이 될 수 있지만, k가 작을 때는 O(k log k + n)이 더 적합하다. +공간복잡도: O(n) + 딕셔너리에 각 숫자의 빈도를 저장하는데 O(n)의 공간이 필요하므로 전체 공간복잡도는 O(n) + +사용한 자료구조: 딕셔너리, 리스트 +''' + + + +import heapq + +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + arr = {} + answ = [] + a = [] + for i in nums: + if i in arr: + arr[i] += 1 + else: + arr[i] = 1 + + a = sorted(arr.items(), key=lambda x:x[1], reverse=True) + for i in range(k): + answ.append(a[i][0]) + return answ + diff --git a/two-sum/ZetBe.py b/two-sum/ZetBe.py new file mode 100644 index 0000000000..3016e013f8 --- /dev/null +++ b/two-sum/ZetBe.py @@ -0,0 +1,52 @@ +''' +문제: 배열 중에서 두 수를 더해서 타겟 넘버가 되는 인덱스를 반환하라 + 한 인덱스를 두번 사용할 수 없으며, 답은 하나만 존재한다. +풀이: 딕셔너리를 이용하여 각 숫자의 인덱스를 저장한 후, + 타겟 넘버에서 각 숫자를 뺀 값이 딕셔너리에 있는지 확인 + 그리고 그 숫자가 두 번 이상 등장하는지 확인 + (절반으로 나누어 떨어지는 경우 고려) + +시간복잡도: O(n) +딕셔너리에 각 숫자를 저장하는데 O(n), 겹치지 않은 수를 탐색하는데 최악의 경우 O(n) +각 숫자에 대해 타겟 넘버에서 뺀 값이 딕셔너리에 있는지 확인하는데 O(1)이므로, 전체 시간복잡도는 O(n) + +공간복잡도: O(n) +딕셔너리에 각 숫자를 저장하는데 O(n)의 공간이 필요하므로 전체 공간복잡도는 O(n) + +사용한 자료구조: 딕셔너리 + +일반 리스트를 사용하여 탐색할 경우, 시간복잡도가 O(n^2)이 될 수 있다. +최악의 경우, n*(n-1)/2번의 탐색이 필요한데, 이는 결국 O(n^2)이다. +''' + +# 추가로 코드리뷰를 통해 가독성 개선한 코드 +''' +for i in range(len(nums)): + if target - nums[i] in d: + return [d[target-nums[i]][0], i] + if nums[i] not in d: + d[nums[i]] = [i] + + else: + + d[nums[i]] += [i] +''' + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + answ = [] + d = {} + for i in range(len(nums)): + if nums[i] not in d: + d[nums[i]] = [i] + else: + d[nums[i]] += [i] + print(d) + for i in d.keys(): + if target-i in d and len(d[target-i]) == 1 and target != i*2: + answ = [d[target-i][0], d[i][0]] + return answ + if target-i in d and len(d[target-i]) >= 2 and target == i*2: + answ = [d[target-i][0], d[i][1]] + return answ +