LeetCode#15 | Three Sum 三数之和
Posted 呦呦鹿鸣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}
以上是关于LeetCode#15 | Three Sum 三数之和的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 1013. Partition Array Into Three Parts With Equal Sum
(Easy) Partition Array Into Three Parts With Equal Sum - LeetCode