LeetCode#15-Three Sum-三数之和
一、题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
二、题解
思路1:
之前有道算法题,是求两数之和,所以想法就是先遍历数组,固定当前元素,并求出当前元素的相反数,即剩下两个数的和sum;然后转化成 twoSum;最后去重。
本地跑是没问题的,但是,在力扣上提交代码,等待系统判分后,执行结果是超出时间限制——系统给的输入是好大一段数组,里面得有几百个数字吧?!🤣所以下面的代码适合小数组。
function threeSum($nums) {
$result = [];
$len = count($nums);
for ($i = 0; $i < $len; $i++) {
$a = $nums[$i];
$sum = ($a > 0) ? 0 - $a : abs($a);
$searched = [];
for ($j = 0; $j < $len; $j++) {
if ($j == $i) {
continue;
}
if (!in_array($sum - $nums[$j], $searched)) {
$searched[] = $nums[$j];
} else {
$tmp = [$a, $nums[$j], $sum - $nums[$j]];
sort($tmp);
if (in_array($tmp, $result)) {
continue;
}
$result[] = $tmp;
}
}
}
return $result;
}
思路2:双指针法
首先剔除一些特殊情况:①数组元素个数小于3;②排序后最小值大于0;③排序后最大值小于0;
对数组进行排序;
从第一个元素开始,遍历至倒数第三个元素;
每一次遍历中,使用双指针处理该元素右侧的数组,问题基本转化为 twoSum:
①用两个变量 low 和 high 指向数组的开头和结尾;
②因为已经进行过排序,如果nums[low]+nums[high] < sum,则说明low指向的数太小,需要往后移动;
③反之,则是high指向的数太大,需要前移;
④当两者相等,未避免得到重复的三元组集合,遇到重复的数字就跳过。
function threeSum($nums) {
$len = count($nums);
if ($len < 3) {
return [];
}
sort($nums);
if ($nums[0] > 0 || end($nums) < 0) {
return [];
}
$res = [];
for ($i = 0; $i < $len; $i++) {
// 如果 i 与 i-1 值相同,说明上一次比较过了
if ($nums[$i] == $nums[$i-1]) {
continue;
}
// 要对比的值
$target = 0 - $nums[$i];
$low = $i + 1;
$high = $len - 1;
while ($low < $high) {
if ($nums[$low] + $nums[$high] == $target) {
$res[] = [$nums[$i], $nums[$low], $nums[$high]];
// 因为数组已经排好序,且要求返回的组合不能重复
// 如果nums[low] == nums[low+1] 说明两个数重复,数据组合会重合。将 low 向后偏移一位
while ($low < $high && $nums[$low] == $nums[$low + 1]) {
$low ++;
}
// 如果nums[high] == nums[high-1] 说明两个数重复,数据组合会重合。将 high 向前偏移一位
while ($low < $high && $nums[$high] == $nums[$high - 1]) {
$high --;
}
// low 与 high 这对组合已经使用过,因此需要继续偏移
$low ++;
$high --;
} else if ($nums[$low] + $nums[$high] < $target) {
$low ++;
} else {
$high --;
}
}
}
return $res;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现