题目
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解题
思路是先将数组排序,再建立一个for循环,依次取到数组中的数字,然后将该数字后一位作为 left ,数组最后一位作为 right ,三个数字相加,检查是否为0。
因为数组是有序的,如果三数之和<0,我们的目的是三数之和等于0,那么需要舍弃掉 left,即left++(因为left小于right,要使结果变大,必须加上一个大一点的数)。
反之如果三数之和>0,同理舍弃right,即right - -。
public IList<IList<int>> ThreeSum(int[] nums) {
int len = nums.Length;
IList<IList<int>> ans = new List<IList<int>>();
if (nums == null || len < 3) return ans;
Array.Sort(nums);
for(int i = 0; i < len-2; i++)
{
if (nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1;
int right = len - 1;
while (left < right)
{
int sum=nums[i] + nums[left] + nums[right];
if ( sum == 0)
{
ans.Add(new List<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--;
}
else if (nums[i] + nums[left] + nums[right] < 0) left++;
else if (nums[i] + nums[left] + nums[right] > 0) right--;
}
}
return ans;
}
需要注意的点:
1.当数组中包含的数少于三个或者数组为空时,直接返回空的list;
2.需要对数组先排序,再开始遍历,便于去重,例如{ -4,-4,0,1,2,2},如果找到答案[ -4,2,2],该 -4是第一个 -4,那么我们应该跳过第二个 -4;
3.如果第一个数大于0,那么三数之和不可能等于0,例如{ 2,3,4,5};
4.如果找到了三个数的和为0,那么left和right应该同时移动,移动之前还需要判断left与left+1是否相同,相同则跳过left+1,判断right是否与right-1相同,相同则跳过right-1。
参考:https://leetcode-cn.com/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/