哈希表
8. 三数之和
思路:
确定两个数字找第三个数字。去重非常麻烦!
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int nums_size = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
for (int i = 0; i < nums_size; i++) {
if (nums[i] > 0) break; // 最小的数大于 0,则没有答案了
if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重
unordered_set<int> my_set;
for (int j = i + 1; j < nums_size; j++) {
if (j > i + 2 && nums[j - 1] == nums[j - 2] && nums[j] == nums[j - 1]) continue;
int c = 0 - nums[i] - nums[j];
if (my_set.find(c) != my_set.end()) {
ans.push_back({nums[i], nums[j], c});
my_set.erase(c);
} else {
my_set.insert(nums[j]);
}
}
}
return ans;
}
};
思路2:
双指针法,思路如下动图:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int nums_size = nums.size();
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums_size - 2; i++) {
if (nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1, right = nums_size - 1;
while (left < right) {
if (nums[i] + nums[left] + nums[right] > 0) right--;
else if (nums[i] + nums[left] + nums[right] < 0) left++;
else {
ans.push_back(vector<int>{nums[i], nums[left], nums[right]});
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
}
}
}
return ans;
}
};
9. 四数之和
思路:
思路和三数之和相同,只不过多了一层循环。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
int nums_size = nums.size();
sort(nums.begin(), nums.end());
for (int k = 0; k < nums_size - 3; k++) {
if (nums[k] > target && nums[k] > 0) break; // 剪枝
if (k > 0 && nums[k] == nums[k - 1]) continue; // 去重
for (int i = k + 1; i < nums_size - 2; i++) {
if (nums[k] + nums[i] > target && nums[k] + nums[i] > 0) break; // 二级剪枝
if (i > k + 1 && nums[i] == nums[i - 1]) continue; // 去重
int left = i + 1, right = nums_size - 1;
while (left < right) {
if ((long)nums[k] + nums[i] + nums[left] + nums[right] < target) left++; // 转成 long 类型,否则可能加和溢出
else if ((long)nums[k] + nums[i] + nums[left] + nums[right] > target) right--;
else {
result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
}
}
}
}
return result;
}
};