diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index f7146907..1685db74 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -34,7 +34,7 @@ ### 哈希解法 -两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。 +两层for循环就可以确定 两个数值,可以使用哈希法来确定 第三个数 0-(a+b) 或者 0 - (a + c) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。 把符合条件的三元组放进vector中,然后再去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。 @@ -48,35 +48,41 @@ ```CPP class Solution { public: + // 在一个数组中找到3个数形成的三元组,它们的和为0,不能重复使用(三数下标互不相同),且三元组不能重复。 + // b(存储)== 0-(a+c)(检索) vector> threeSum(vector& nums) { vector> result; sort(nums.begin(), nums.end()); - // 找出a + b + c = 0 - // a = nums[i], b = nums[j], c = -(a + b) + for (int i = 0; i < nums.size(); i++) { - // 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 - if (nums[i] > 0) { + // 如果a是正数,a 0) break; - } - if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重 + + // [a, a, ...] 如果本轮a和上轮a相同,那么找到的b,c也是相同的,所以去重a + if (i > 0 && nums[i] == nums[i - 1]) continue; - } + + // 这个set的作用是存储b unordered_set set; - for (int j = i + 1; j < nums.size(); j++) { - if (j > i + 2 - && nums[j] == nums[j-1] - && nums[j-1] == nums[j-2]) { // 三元组元素b去重 + + for (int k = i + 1; k < nums.size(); k++) { + // 去重b=c时的b和c + if (k > i + 2 && nums[k] == nums[k - 1] && nums[k - 1] == nums[k - 2]) continue; + + // a+b+c=0 <=> b=0-(a+c) + int target = 0 - (nums[i] + nums[k]); + if (set.find(target) != set.end()) { + result.push_back({nums[i], target, nums[k]}); // nums[k]成为c + set.erase(target); } - int c = 0 - (nums[i] + nums[j]); - if (set.find(c) != set.end()) { - result.push_back({nums[i], nums[j], c}); - set.erase(c);// 三元组元素c去重 - } else { - set.insert(nums[j]); + else { + set.insert(nums[k]); // nums[k]成为b } } } + return result; } };