-
-
Notifications
You must be signed in to change notification settings - Fork 358
[dolphinflow86] WEEK 01 Solutions #2641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
90fb6db
49f79f6
a750bac
e784558
97883c1
0d1e9d8
d358884
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n) | O(n) | ✅ |
| Space | O(n) | O(n) | ✅ |
피드백: 집합을 사용하여 각 원소를 한 번씩만 검사하므로 시간 복잡도는 선형이고, 집합 저장에 선형 공간이 필요합니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.containsDuplicate — Time: ✅ O(n^2) → O(n^2) / Space: ✅ O(1) → O(1)
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n^2) | O(n^2) | ✅ |
| Space | O(1) | O(1) | ✅ |
피드백: 이중 루프로 모든 원소 쌍을 검사하므로 시간 복잡도는 이차이며, 공간은 상수입니다.
개선 제안: 시간 복잡도를 개선하려면 정렬 후 인접 원소 비교 방법을 고려할 수 있습니다.
풀이 3: Solution.containsDuplicate — Time: ✅ O(n log n) → O(n log n) / Space: ❌ O(n) → O(1)
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n log n) | O(n log n) | ✅ |
| Space | O(n) | O(1) | ❌ |
피드백: 배열을 정렬하는 데 O(n log n) 시간이 소요되고, 이후 인접 원소 비교로 선형 시간에 검사 가능합니다.
개선 제안: 현재 구현이 적절해 보입니다.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # First approach: using a set to check for duplicates while iterating through nums | ||
| # TC: O(n), where n is the number of elements in nums | ||
| # SC: O(n), where n is the number of elements in nums | ||
| class Solution: | ||
| def containsDuplicate(self, nums: List[int]) -> bool: | ||
| seen = set() | ||
|
|
||
| for num in nums: | ||
| # check if the number exists in the set during each iteration | ||
| if num in seen: | ||
| return True | ||
| seen.add(num) | ||
|
|
||
| return False | ||
|
|
||
|
|
||
| # Second approach: brute-force method using nested for loops to check every pair for duplicates. | ||
| # Inefficient time complexity (quadratic time) but has a constant space complexity. | ||
| # TC: O(n^2), where n is the number of elements in nums | ||
| # SC: O(1) | ||
| class Solution: | ||
| def containsDuplicate(self, nums: List[int]) -> bool: | ||
| for i in range(len(nums)): | ||
| for j in range(i + 1, len(nums)): | ||
| if nums[i] == nums[j]: | ||
| return True | ||
|
|
||
| return False | ||
|
|
||
|
|
||
| # Third approach: to decrease time complexity from the brute-force approach, by sorting the array and comparing adjacent elements | ||
| # TC: O(n log n), where n is the number of elements in nums | ||
| # SC: O(n), where n is the number of elements in nums. Initially I thought Python's sorting algorithm was the same as C++'s IntroSort. | ||
| # However, Python uses Timsort uses which requires O(n) space in the worst case | ||
| class Solution: | ||
| def containsDuplicate(self, nums: List[int]) -> bool: | ||
| nums.sort() | ||
|
|
||
| # Compare adjacent elements | ||
| for i in range(len(nums) - 1): | ||
| if nums[i] == nums[i + 1]: | ||
| return True | ||
|
|
||
| return False |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 각 집에 대해 한 번씩 계산하며, 메모이제이션으로 중복 계산을 방지하므로 시간 복잡도는 선형이고, 저장 공간도 선형입니다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Solved using a top down dp (memoization) approach. | ||
| # TC: O(N) where N = len(nums) - Each house is visited at most once due to caching. | ||
| # SC: O(N) where N = len(nums) - Used for the memoization dictionary and recursion call stack. | ||
| class Solution: | ||
| def rec(self, house: int, nums: List[int], memo: Dict[int,int]) -> int: | ||
| if house >= len(nums): return 0 | ||
|
|
||
| if house in memo: return memo[house] | ||
|
|
||
| # max between (robbing current house + skipping next) or (skipping current house) | ||
| current_robbed = max(nums[house] + self.rec(house + 2, nums, memo), self.rec(house + 1, nums, memo)) | ||
| memo[house] = current_robbed | ||
| return current_robbed | ||
|
|
||
| def rob(self, nums: List[int]) -> int: | ||
| memo: Dict[int,int] = {} | ||
| return self.rec(0, nums, memo) |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 집합을 통해 O(1) 탐색으로 연속 수를 찾으며, 각 수는 최대 한 번씩만 처리되어 전체 시간은 선형입니다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Calculate the length of the streak from its starting point. | ||
| # TC: O(N) where N is the size of nums | ||
| # SC: O(N) where N is the size of nums | ||
| class Solution: | ||
| def longestConsecutive(self, nums: List[int]) -> int: | ||
| # convert list to set for O(1) lookups | ||
| num_set: Set[int] = set(nums) | ||
| max_streak = 0 | ||
|
|
||
| for num in num_set: | ||
| if num - 1 in num_set: | ||
| continue | ||
|
|
||
| # found streak starting point | ||
| streak = 0 | ||
| cur_num = num | ||
|
|
||
| # extend the streak as long as consecutive numbers exists | ||
| while cur_num in num_set: | ||
| streak += 1 | ||
| cur_num += 1 | ||
|
|
||
| # update max streak | ||
| max_streak = max(streak, max_streak) | ||
|
|
||
| return max_streak |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 빈도수 맵과 버킷 배열을 사용하여 빈도별로 원소를 분류하므로 시간은 선형이고, 공간도 선형입니다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # 1) Using modified bucket sort approach. | ||
| # TC: O(N) where N is the length of nums | ||
| # SC: O(N) where N is the length of nums | ||
| class Solution: | ||
| def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||
| freq_map = {} | ||
|
|
||
| bucket_count = len(nums) | ||
| for num in nums: | ||
| freq_map[num] = freq_map.get(num, 0) + 1 | ||
|
|
||
| buckets = [[] for i in range(bucket_count + 1)] | ||
|
|
||
| for num, freq in freq_map.items(): | ||
| buckets[freq].append(num) | ||
|
|
||
| top_list = [] | ||
| for i in range(bucket_count, -1, -1): | ||
| for num in buckets[i]: | ||
| top_list.append(num) | ||
| if len(top_list) == k: | ||
| return top_list |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n^2) | O(n^2) | ✅ |
| Space | O(1) | O(1) | ✅ |
피드백: 모든 쌍을 검사하므로 시간 복잡도는 이차이며, 공간은 상수입니다.
개선 제안: 해시맵을 이용한 방법으로 시간 복잡도를 개선할 수 있습니다.
풀이 2: Solution.twoSum — Time: ❌ O(2*n) → O(n) / Space: ✅ O(n) → O(n)
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(2*n) | O(n) | ❌ |
| Space | O(n) | O(n) | ✅ |
피드백: 한 번의 순회로 원소와 그 보수값을 저장하며, 검색도 O(1)로 수행되어 전체 시간은 선형입니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 3: Solution.twoSum — Time: ✅ O(n) → O(n) / Space: ✅ O(n) → O(n)
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n) | O(n) | ✅ |
| Space | O(n) | O(n) | ✅ |
피드백: 보수값을 저장하면서 탐색하는 방식으로, 시간 복잡도는 선형이고 공간도 선형입니다.
개선 제안: 현재 구현이 적절해 보입니다.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # 1) Using nested for loop to find every possible combination for target sum | ||
| # TC: O(n^2) where n is the size of nums | ||
| # SC: O(1) | ||
| class Solution: | ||
| def twoSum(self, nums: List[int], target: int) -> List[int]: | ||
| for i in range(len(nums)): | ||
| for j in range(i + 1, len(nums)): | ||
| if nums[i] + nums[j] == target: | ||
| return [i , j] | ||
|
|
||
| return [] | ||
|
|
||
| #2) Using two pass approach with hash map so that find out complement with index. | ||
| # TC: O(2*n) -> O(n) where n is the size of nums | ||
| # SC: O(n) where n is the size of nums | ||
| class Solution: | ||
| def twoSum(self, nums: List[int], target: int) -> List[int]: | ||
| seen: dict[int, int] = {} | ||
|
|
||
| for i in range(len(nums)): | ||
| seen[nums[i]] = i | ||
|
|
||
| for i in range(len(nums)): | ||
| complement = target - nums[i] | ||
| if complement in seen and i != seen[complement]: | ||
| return [seen[complement], i] | ||
|
|
||
| return [] | ||
|
|
||
| # 3) Tiny optimize from two pass version. Instead of inserting separately, insert within one loop | ||
| # TC: O(n), where n is the size of nums | ||
| # SC: O(n), where n is the size of nums | ||
| class Solution: | ||
| def twoSum(self, nums: List[int], target: int) -> List[int]: | ||
| seen: dict[int, int] = {} | ||
|
|
||
| for i in range(len(nums)): | ||
| complement = target - nums[i] | ||
| if complement in seen: | ||
| return [seen[complement], i] | ||
|
|
||
| seen[nums[i]] = i | ||
|
|
||
| return [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DaleStudy/coach 풀이 3에서 파이썬의 정렬 알고리즘인 팀소트는 내부적으로 최악의 경우 O(n)의 공간복잡도를 가지는 것으로 알고 있는데 혹시 그 부분이 평가에 고려되었을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네, 맞습니다. 파이썬의 Timsort는 최악의 경우 O(n)의 공간복잡도를 사용합니다. 코멘트에서도 언급했듯이, 정렬 후 인접 원소 비교 방식은 시간 복잡도는 O(n log n)이고, 공간복잡도는 O(n)입니다. 따라서 평가 시 이 점이 고려될 수 있으며, 공간 효율성을 중시한다면 다른 방법(예: 해시셋 활용)이 더 적합할 수 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DaleStudy/coach 아! 풀이3에 검토해주신 공간복잡도 분석이 실패로 표기되어 있어서 질문드렸습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
풀이3에서 Timsort의 공간복잡도는 최악의 경우 O(n)입니다. 이는 정렬 과정에서 배열을 임시로 저장하는 데 필요한 공간 때문입니다. 따라서, 코드에 적힌 SC: O(n)은 맞는 분석입니다. 만약 더 자세한 설명이 필요하면, Timsort는 최악의 경우에도 O(n) 공간을 사용하며, 이는 Python의 내장 정렬이 안정성과 성능을 위해 사용하는 알고리즘입니다.