Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions contains-duplicate/dolphinflow86.py

Copy link
Copy Markdown
Contributor Author

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)의 공간복잡도를 가지는 것으로 알고 있는데 혹시 그 부분이 평가에 고려되었을까요?

Copy link
Copy Markdown
Contributor

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)입니다. 따라서 평가 시 이 점이 고려될 수 있으며, 공간 효율성을 중시한다면 다른 방법(예: 해시셋 활용)이 더 적합할 수 있습니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DaleStudy/coach 아! 풀이3에 검토해주신 공간복잡도 분석이 실패로 표기되어 있어서 질문드렸습니다.

Copy link
Copy Markdown
Contributor

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의 내장 정렬이 안정성과 성능을 위해 사용하는 알고리즘입니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Hash Map / Hash Set, Sorting
  • 설명: 첫 번째 방법은 set을 이용한 중복 체크로 Hash Map/Set 패턴에 속하며, 세 번째 방법은 정렬 후 인접 비교로 Sorting 패턴을 사용합니다. 두 패턴 모두 중복 검출에 효과적입니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 3가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Solution.containsDuplicate — Time: ✅ O(n) → O(n) / Space: ✅ O(n) → O(n)
유저 분석 실제 분석 결과
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
17 changes: 17 additions & 0 deletions house-robber/dolphinflow86.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Dynamic Programming
  • 설명: 이 코드는 메모이제이션을 활용한 최적 부분 구조를 이용한 DP 접근 방식으로, 각 집을 털었을 때와 안 털었을 때의 최적 값을 계산하여 최대 이익을 구합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(N) O(n)
Space O(N) O(n)

피드백: 각 집에 대해 한 번씩 계산하며, 메모이제이션으로 중복 계산을 방지하므로 시간 복잡도는 선형이고, 저장 공간도 선형입니다.

개선 제안: 현재 구현이 적절해 보입니다.

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)
26 changes: 26 additions & 0 deletions longest-consecutive-sequence/dolphinflow86.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Hash Map / Hash Set, Union Find
  • 설명: 이 코드는 숫자 집합을 이용해 연속된 수를 찾으며, Hash Set을 활용한 O(1) 탐색으로 최장 연속 수열을 구하는 방식입니다. Union Find는 사용되지 않지만, 집합 기반 탐색이 핵심입니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(N) O(n)
Space O(N) O(n)

피드백: 집합을 통해 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
22 changes: 22 additions & 0 deletions top-k-frequent-elements/dolphinflow86.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Bucket Sort
  • 설명: 이 코드는 빈도수별로 데이터를 분류하는 버킷 정렬 방식을 활용하여, 최빈값을 빠르게 찾는 방식입니다. 주어진 문제에 특화된 정렬 기법으로 효율성을 높였습니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(N) O(n)
Space O(N) O(n)

피드백: 빈도수 맵과 버킷 배열을 사용하여 빈도별로 원소를 분류하므로 시간은 선형이고, 공간도 선형입니다.

개선 제안: 현재 구현이 적절해 보입니다.

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
44 changes: 44 additions & 0 deletions two-sum/dolphinflow86.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Hash Map / Hash Set
  • 설명: 두 번째와 세 번째 방법은 해시 맵을 이용해 보조 자료구조를 활용하여 시간 복잡도를 개선하는 방식으로, 해시 맵 패턴에 속합니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 3가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: Solution.twoSum — Time: ✅ O(n^2) → O(n^2) / Space: ✅ O(1) → O(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 []
Loading