双指针算法详解:三数之和与四数之和
排序加双指针方法解决三数之和与四数之和问题。核心思路是固定部分元素后转化为两数或三数之和问题,利用双指针在有序数组中查找目标和。重点在于处理重复元素,通过跳过相同数值避免结果冗余。代码使用 C++ 实现,包含详细注释与逻辑解析,适用于面试准备及算法能力提升。

排序加双指针方法解决三数之和与四数之和问题。核心思路是固定部分元素后转化为两数或三数之和问题,利用双指针在有序数组中查找目标和。重点在于处理重复元素,通过跳过相同数值避免结果冗余。代码使用 C++ 实现,包含详细注释与逻辑解析,适用于面试准备及算法能力提升。



解法:(排序 + 双指针)
本题与之前讲解的两数之和为 s 类似,是非常经典的面试题。
与两数之和稍微不同的是,题目中要求找到所有【不重复】的三元组。那我们可以利用在两数之和为 s 那里的双指针思想:
但是我们需要注意的是,这道题里面需要有【去重】操作!
找到一个结果之后,不要停,left++,right--缩小区间后,left 和 right 指针也要【跳过重复】的元素;
当使用完一次双指针算法之后,固定的 stub 也要【跳过重复】的元素。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
// 解法一:使用去重容器 set(笔试可以直接秒题,但代码效率低)
// sort(nums.begin(), nums.end());
// vector<vector<int>> vv;
// set<vector<int>> s;
// int stub = nums.size() - 1;
// while(stub > 1 && nums[stub] >= 0) {
// int left = 0;
// int right = stub - 1;
// while(left < right) {
// if(nums[left] + nums[right] + nums[stub] > 0) {
// right--;
// } else if(nums[left] + nums[right] + nums[stub] < 0) {
// left++;
// } else{
// s.insert({nums[left], nums[right], nums[stub]});
// left++;
// right--;
// }
// }
// stub--;
// }
// for(auto e : s) {
// vv.push_back(e);
// }
// return vv;
// 解法二:不使用容器去重 (针对面试,可以提升算法能力,而且代码效率高)
sort(nums.begin(), nums.end());
vector<vector<int>> vv;
int stub = nums.size() - 1;
while(stub > 1 && nums[stub] >= 0) {
int left = 0;
int right = stub - 1;
while(left < right) {
if(nums[left] + nums[right] + nums[stub] > 0) {
right--;
} else if(nums[left] + nums[right] + nums[stub] < 0) {
left++;
} else{
vv.push_back({nums[left], nums[right], nums[stub]});
while(left < right && nums[left] == nums[left + 1]) {
left++;
}
while(left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
}
}
while(stub > 1 && nums[stub] == nums[stub - 1]) {
stub--;
}
stub--;
}
return vv;
}
};




解法:(排序 + 双指针)
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
vector<vector<int>> vv;
for(int i = 0; i < nums.size(); i++) {
for(int j = i + 1; j < nums.size(); j++) {
int left = j + 1;
int right = nums.size() - 1;
while(left < right) {
long long sum = (long long)nums[i] + nums[j] + nums[left] + nums[right];
// 注意:使用 long long 防止整数溢出
if(sum > target) {
right--;
} else if(sum < target) {
left++;
} else{
vv.push_back({nums[i], nums[j], nums[left], nums[right]});
while(left < right && nums[left] == nums[left + 1]) {
left++;
}
while(left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
}
}
while(j < nums.size() - 1 && nums[j] == nums[j + 1]) {
j++;
}
}
while(i < nums.size() - 1 && nums[i] == nums[i + 1]) {
i++;
}
}
return vv;
}
};

至此,三数之和与四数之和两道算法题讲解完毕。通过排序 + 双指针算法优化暴力解法,重点讲解了去重操作的实现方法。对于三数之和,固定一个数后用双指针在剩余区间寻找两数之和;四数之和则通过固定两个数后转化为三数之和问题。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online