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
4 changes: 3 additions & 1 deletion algorithms/arrays/remove_duplicates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ and 4 respectively. It doesn't matter what values are set beyond the returned le

Constraints:

0 <= nums.length <= 3 * 104 -104 <= nums[i] <= 104 nums is sorted in ascending order.
- 0 <= nums.length <= 3 * 10^4
- -10^4 <= nums[i] <= 10^4
- nums is sorted in ascending order.

---

Expand Down
6 changes: 6 additions & 0 deletions algorithms/arrays/remove_duplicates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@ def remove_duplicates_from_sorted_list(nums: List[int]) -> int:
if not nums:
return 0

# i tracks the position where the next unique element should be placed.
# Start j from index 1 and iterate through the list to find unique elements.
i, j = 0, 1

while j < len(nums):
# If the current element is different from the last unique element found:
if nums[i] != nums[j]:
# Move i forward to store the new unique element
i += 1
# Place the unique element in its correct position
nums[i] = nums[j]
j += 1
# Return the count of unique elements (index i + 1 because i is zero-based)
return i + 1


Expand Down
41 changes: 41 additions & 0 deletions algorithms/two_pointers/three_sum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,44 @@ at least 2 more elements after i for left and right to form a triplet.

![Solution 18](./images/solutions/three_sum_solution_18.png)
![Solution 19](./images/solutions/three_sum_solution_19.png)

---

# Three Number Sum

Write a function that takes in a non-empty array of distinct integers and an
integer representing a target sum. The function should find all triplets in
the array that sum up to the target sum and return a two-dimensional array of
all these triplets. The numbers in each triplet should be ordered in ascending
order, and the triplets themselves should be ordered in ascending order with
respect to the numbers they hold.

If no three numbers sum up to the target sum, the function should return an
empty array.

## Examples

Example 1

```text
array = [12, 3, 1, 2, -6, 5, -8, 6]
targetSum = 0
[[-8, 2, 6], [-8, 3, 5], [-6, 1, 5]]
```

## Hints

- Using three for loops to calculate the sums of all possible triplets in the array would generate an algorithm that runs
in O(n^3) time, where n is the length of the input array. Can you come up with something faster using only two for loops?
- Try sorting the array and traversing it once. At each number, place a left pointer on the number immediately to the
right of your current number and a right pointer on the final number in the array. Check if the current number, the
left number, and the right number sum up to the target sum. How can you proceed from there, remembering the fact that
you sorted the array?
- Since the array is now sorted (see Hint #2), you know that moving the left pointer mentioned in Hint #2 one place to
the right will lead to a greater left number and thus a greater sum. Similarly, you know that moving the right pointer
one place to the left will lead to a smaller right number and thus a smaller sum. This means that, depending on the
size of each triplet's (current number, left number, right number) sum relative to the target sum, you should either
move the left pointer, the right pointer, or both to obtain a potentially valid triplet.

> The solution here will be the same as the Three Sum problem above, with the only difference being the targetSum is not
> 0 and has been provided as an input
34 changes: 34 additions & 0 deletions algorithms/two_pointers/three_sum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,37 @@ def three_sum(nums: List[int]) -> List[List[int]]:
right -= 1

return result


def three_number_sum(array: List[int], target_sum: int) -> List[List[int]]:
if not array:
return []

# Sort the array and store the result in nums to avoid side effects to the caller of this
# function. This incurs a a time complexity of O(n (log(n))) and a space complexity of O(n)
# where n is the number of elements in the array
nums = sorted(array)
n = len(nums)
result = []

for idx, num in enumerate(nums):
left = idx + 1
right = n - 1

while left < right:
total = num + nums[left] + nums[right]
if total == target_sum:
result.append([num, nums[left], nums[right]])
# move the left pointer to avoid duplicates while it is still less than the right
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
elif total > target_sum:
right -= 1
else:
left += 1

return result
15 changes: 14 additions & 1 deletion algorithms/two_pointers/three_sum/test_three_sum.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest
from typing import List
from parameterized import parameterized
from algorithms.two_pointers.three_sum import three_sum
from algorithms.two_pointers.three_sum import three_sum, three_number_sum

THREE_SUM_TEST_CASES = [
([-1, 0, 1, 2, -1, -4], [[-1, -1, 2], [-1, 0, 1]]),
Expand All @@ -14,6 +14,10 @@
([-1, 0, 1, 2, -1, -4, -1, 2, 1], [[-1, -1, 2], [-1, 0, 1], [-4, 2, 2]]),
]

THREE_NUMBER_SUM_TEST_CASES = [
([12, 3, 1, 2, -6, 5, -8, 6], 0, [[-8, 2, 6], [-8, 3, 5], [-6, 1, 5]]),
]


class ThreeSumTestCases(unittest.TestCase):
@parameterized.expand(THREE_SUM_TEST_CASES)
Expand All @@ -22,5 +26,14 @@ def test_three_sum(self, nums: List[int], expected: List[List[int]]):
self.assertEqual(expected, actual)


class ThreeNumberSumTestCases(unittest.TestCase):
@parameterized.expand(THREE_NUMBER_SUM_TEST_CASES)
def test_three_number_sum(
self, nums: List[int], target_sum: int, expected: List[List[int]]
):
actual = three_number_sum(nums, target_sum)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
Loading