Skip to content

Problem 15 #25

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

Merged
merged 3 commits into from
Aug 23, 2022
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ As I work through this list I figure I would make a GitHub repo with my solution
27. [01 Matrix #542](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/01-matrix-542.md)
28. [K Closest Points to Origin #973](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/k-closest-origin-973.md)
29. [Longest Substring Without Repeating Characters #3](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/longest-substring-3.md)
30. 3Sum #15
30. [3Sum #15](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/3sum-15.md)
31. Binary Tree Level Order Traversal #102
32. Clone Graph #133
33. Evaluate Reverse Polish Notation #150
Expand Down Expand Up @@ -104,6 +104,7 @@ In order to practice with similar data structures I'll be placing each problem i
- [K Closest Points to Origin #973](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/k-closest-origin-973.md)
- [Insert Interval #57](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/insert-interval-57.md)
- [01 Matrix #542](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/01-matrix-542.md)
- [3Sum #15](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/3sum-15.md)

### Queue

Expand Down Expand Up @@ -140,6 +141,7 @@ In order to practice with similar data structures I'll be placing each problem i
- [Majority Element #169](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/majority-element-169.md)
- [Contains Duplicate #217](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/contains-duplicate-217.md)
- [Longest Substring Without Repeating Characters #3](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/longest-substring-3.md)
- [3Sum #15](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/3sum-15.md)

### Binary Tree

Expand All @@ -165,6 +167,7 @@ Within the problems above there are several patterns that often occur. I plan to
- [Reverse Linked List #206](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/reverse-linked-list-206.md)
- [Middle of the Linked List #876](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/middle-linked-list-876.md)
- [Contains Duplicate #217](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/contains-duplicate-217.md)
- [3Sum #15](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/3sum-15.md)

### Sliding Window

Expand Down
122 changes: 122 additions & 0 deletions medium/3Sum-15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# 3Sum

Page on leetcode: https://leetcode.com/problems/3sum/

## Problem Statement

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

### Constraints

- 3 <= nums.length <= 3000
- -10<sup>5</sup> <= nums[i] <= 10<sup>5</sup>

### Example

```
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.
```

```
Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.
```

```
Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.
```

## Solution

- No duplicates of triplets (Can I exclude with a hashmap?)
- Brute force possible with an O(n<sup>3</sup>) solution
- Approach like two sum and store pairs as key's and remainder as values?
- All possibilities is n<sup>3</sup> (aka a cube) Some of these are complimentary, how can we eliminate those so we don't have to calc twice?

### Pseudocode Attempt

1. Create map
2. Create result
3. Iterate thru nums with i
4. Iterate thru nums with j = i + 1
5. Store 0 - nums[i] - nums[j] in map with [nums[i], nums[j], false]
6. If found add to result and change to true, if true don't add to result
7. return result

### Initial Attempt

```javascript
const threeSum = function (nums) {
const map = {};
const result = [];

for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
const remainder = 0 - nums[i] - nums[j];
if (remainder in map) {
// Check if combo was already used
if (!map[remainder][2]) {
result.push([remainder, nums[i], nums[j]]);
}
} else {
map[remainder] = [nums[i], nums[j], false];
}
}
}

return result;
};
```

### Optimized Solution

The time complexity of below is O(n<sup>2</sup>) with a space complexity likely O(n) due to the sorting. https://www.youtube.com/watch?v=jzZsG8n2R9A

```javascript
const threeSum = function (nums) {
const result = [];
nums.sort((a, b) => a - b);

for (let i = 0; i < nums.length; i++) {
// This is an optimization as it exits iterating over the sorted array when num[i] becomes positive. Only positive numbers would be left in the array and you can't add them to make zero
if (nums[i] > 0) {
break;
}

if (i > 0 && nums[i] === nums[i - 1]) {
continue;
}

let l = i + 1;
let r = nums.length - 1;
while (l < r) {
const total = nums[i] + nums[l] + nums[r];
if (total > 0) {
r--;
} else if (total < 0) {
l++;
} else {
result.push([nums[i], nums[l], nums[r]]);
l++;
while (nums[l] === nums[l - 1] && l < r) {
l++;
}
}
}
}

return result;
};
```