3Sum
Problem
Section titled “Problem”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.
Solution approach
Section titled “Solution approach”Intuition
Section titled “Intuition”Duplicate triplets are the main difficulty, so the code works with the distinct values of nums and a frequency map mp. Every valid triplet falls into exactly one of three shapes: three different values, two equal values plus a third, or {0, 0, 0}. Each shape can be checked separately using the counts in mp.
For three different values, fixing a pair arr[i], arr[j] determines the third value -(arr[i] + arr[j]), which a hash lookup checks in . This avoids the brute force over all triples. Each triplet is sorted and stored in a set so repeats are dropped.
Algorithm
Section titled “Algorithm”- Count every value in
mp, copy the distinct values intoarr, and sortarr. - All different: for every pair
i,jof distinct values, letsm = arr[i] + arr[j]. If-smdiffers from both andmp[-sm] > 0, sort the triplet and insert it intoans. - Two equal: for every
arr[i] != 0withmp[arr[i]] > 1, check whether-2 * arr[i]exists; if so, insert{arr[i], arr[i], -2 * arr[i]}. - All equal: if
mp[0] > 2, insert{0, 0, 0}. - Copy the set
ansinto the vectorvvand return it.
Complexity
Section titled “Complexity”- Time: — pairs of distinct values, and each insertion into the ordered
setcosts or more. - Space: — the map and
arrhold up to values and the set holds the unique triplets.
Edge cases
Section titled “Edge cases”- Many zeros such as
[0, 0, 0, 0]: steps 2 and 3 skip zero, and only step 4 adds{0, 0, 0}, once. - A value used twice such as
[-1, -1, 2]: handled by step 3, because step 2 never pairs a value with itself.
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { int n = nums.size(); unordered_map<int, int> mp; for (int i = 0; i < n; i++) { mp[nums[i]]++; }
vector<int> arr; for (auto i : mp) { arr.push_back(i.first); }
set<vector<int>> ans; n = arr.size(); sort(arr.begin(), arr.end()); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int sm = arr[i] + arr[j]; if (-sm != arr[i] && -sm != arr[j] && mp[-sm] > 0) { vector<int> v = {arr[i], arr[j], -sm}; sort(v.begin(), v.end()); ans.insert(v); } } }
for (int i = 0; i < n; i++) { int sm = 2 * arr[i]; if (sm != arr[i] && mp[arr[i]] > 1 && mp[-2 * arr[i]] > 0) { vector<int> v = {arr[i], arr[i], -sm}; sort(v.begin(), v.end()); ans.insert(v); } }
if (mp[0] > 2) { ans.insert({0, 0, 0}); } vector<vector<int>> vv; for (auto i : ans) { vv.push_back(i); } return vv; }};Give it a try first
Attempt the problem on LeetCode — the code will still be here.