diff --git a/include/s0015_3sum.hpp b/include/s0015_3sum.hpp new file mode 100644 index 0000000..b1a4607 --- /dev/null +++ b/include/s0015_3sum.hpp @@ -0,0 +1,20 @@ +#ifndef S0015_3SUM +#define S0015_3SUM + +#include +#include +#include + +using namespace std; + +class Solution1 { + public: + vector> threeSum(vector& nums); +}; + +class Solution2 { + public: + vector> threeSum(vector& nums); +}; + +#endif diff --git a/src/s0015_3sum.cpp b/src/s0015_3sum.cpp new file mode 100644 index 0000000..c7f31a8 --- /dev/null +++ b/src/s0015_3sum.cpp @@ -0,0 +1,79 @@ +#include "s0015_3sum.hpp" + +// 思路一: +// 遍历一次,创建一个哈希表 +// 双重遍历,找 - nums[i] - nums[j] 是否存在于哈希表中 +// 去重的方式: +// 对于每个找到的序列,先排序,如果不存在则添加到结果中。 + +vector> Solution1::threeSum(vector& nums) { + unordered_map map; + vector> result; + int len = nums.size(); + if (len == 0) { + return result; + } + for (int i{0}; i < len; i++) { + map[nums.at(i)] = i; + } + for (int i{0}; i < len; i++) { + for (int j{0}; j < len; j++) { + if (i == j) { + continue; + } else { + if (map.count(0 - nums.at(i) - nums.at(j)) != 0) { + if (i == map[0 - nums.at(i) - nums.at(j)] || + j == map[0 - nums.at(i) - nums.at(j)]) { + continue; + } else { + vector v{nums.at(i), nums.at(j), 0 - nums.at(i) - nums.at(j)}; + sort(v.begin(), v.end()); + // push if not exist + if (std::find(result.begin(), result.end(), v) == result.end()) { + result.push_back(v); + } + } + } + } + } + } + return result; +} + +// 思路二:双指针 +// 先对整个数组排序,然后固定一个数 a ,然后 b, c 从两边往中间靠。 +vector> Solution2::threeSum(vector& nums) { + int n = nums.size(); + sort(nums.begin(), nums.end()); + vector> ans; + // 枚举 a + for (int first = 0; first < n; ++first) { + // 需要和上一次枚举的数不相同 + if (first > 0 && nums[first] == nums[first - 1]) { + continue; + } + // c 对应的指针初始指向数组的最右端 + int third = n - 1; + int target = -nums[first]; + // 枚举 b + for (int second = first + 1; second < n; ++second) { + // 需要和上一次枚举的数不相同 + if (second > first + 1 && nums[second] == nums[second - 1]) { + continue; + } + // 需要保证 b 的指针在 c 的指针的左侧 + while (second < third && nums[second] + nums[third] > target) { + --third; + } + // 如果指针重合,随着 b 后续的增加 + // 就不会有满足 a+b+c=0 并且 b + +TEST(Problem15, Case1) { + vector i{-1, 0, 1, 2, -1, -4}; + vector> o1{{-1, -1, 2}, {-1, 0, 1}}; + vector> o2{{-1, 0, 1}, {-1, -1, 2}}; + Solution1 solution1; + Solution2 solution2; + EXPECT_TRUE(solution1.threeSum(i) == o1 || solution1.threeSum(i) == o2); + EXPECT_TRUE(solution2.threeSum(i) == o1 || solution2.threeSum(i) == o2); +} + +TEST(Problem15, Case2) { + vector i{0, 1, 1}; + vector> o{}; + Solution1 solution1; + Solution2 solution2; + EXPECT_EQ(solution1.threeSum(i), o); + EXPECT_EQ(solution2.threeSum(i), o); +} + +TEST(Problem15, Case3) { + vector i{0, 0, 0}; + vector> o{{0, 0, 0}}; + Solution1 solution1; + Solution2 solution2; + EXPECT_EQ(solution1.threeSum(i), o); + EXPECT_EQ(solution2.threeSum(i), o); +} + +TEST(Problem15, Case4) { + vector i{-1, 0, 1}; + vector> o{{-1, 0, 1}}; + Solution1 solution1; + Solution2 solution2; + EXPECT_EQ(solution1.threeSum(i), o); + EXPECT_EQ(solution2.threeSum(i), o); +} + +TEST(Problem15, Case5) { + vector i{1, 2, -2, -1}; + vector> o{}; + Solution1 solution1; + Solution2 solution2; + EXPECT_EQ(solution1.threeSum(i), o); + EXPECT_EQ(solution2.threeSum(i), o); +}