Skip to content
Open
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
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
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 Set 패턴을 사용하며, 세 번째 방법은 배열 정렬 후 인접 비교로 정렬 기반 패턴을 보여줍니다. 두 패턴 모두 중복 탐지에 효과적입니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 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
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
  • 설명: 두 번째와 세 번째 방법은 해시 맵을 이용해 보완값을 빠르게 찾는 방식으로, 효율적인 검색을 위해 Hash Map 패턴을 사용합니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 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)

피드백: 한 번의 순회로 원소를 저장하고, 두 번째 순회에서 보수값을 찾기 때문에 시간 복잡도는 선형입니다. 해시 맵을 사용하여 빠른 검색이 가능하며, 공간은 저장하는 데 필요합니다.

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

풀이 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