diff --git a/contains-duplicate/dolphinflow86.py b/contains-duplicate/dolphinflow86.py new file mode 100644 index 0000000000..c627f241c2 --- /dev/null +++ b/contains-duplicate/dolphinflow86.py @@ -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 diff --git a/two-sum/dolphinflow86.py b/two-sum/dolphinflow86.py new file mode 100644 index 0000000000..4c863b6ff3 --- /dev/null +++ b/two-sum/dolphinflow86.py @@ -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 []