中等
相关标签
相关企业
提示
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例 1:
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入: nums = [0,1,1]
输出: []
解释: 唯一可能的三元组和不为 0 。
示例 3:
输入: nums = [0,0,0]
输出: [[0,0,0]]
解释: 唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000-105 <= nums[i] <= 105
题解:
这题利用固定一个数,另外两个用双指针遍历和比较容易。但是要满足解的集合互异很难。一开始我想对数组去重,结果不对,因为解集中可以有重复元素。后来选择设i,j,k三个,强行要求i < j < k,并且他们之间可以相同,但是更新时候不能更新到同样的值。也就是说i可以等j,但是遍历完这次i,下一个i不能等于上一个i。 跳过方法可以用continue,跳过当前循环剩余语句;或者用while自增直到不同。
事实上,做好什么时候需要去重,什么时候不需要去重复,这道题其实不难。
#include <stdio.h>
#include <stdlib.h>
void order(int* nums, int size)
{
int i, j, temp;
for (i = 1;i <= size - 1;i ++)
{
for (j = 0;j <= size - 1 - i;j ++)
{
if (nums[j] > nums[j + 1])
{
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
}
int delorderedsame(int* nums, int size)
{
int slow = 0, fast = 0, newsize;
while (fast <= size - 1)
{
if (nums[fast] > nums[slow])
{
slow ++;
nums[slow] = nums[fast];
fast ++;
}
else
{
fast ++;
}
}
newsize = slow + 1;
return newsize;
}
int main()
{
int size, i, j, k;
scanf("%d", &size);
int* nums = (int*)malloc(sizeof(int) * size);
for (i = 0;i <= size - 1;i ++)
{
scanf("%d", &nums[i]);
}
order(nums, size);
//size = delorderedsame(nums, size);//数组本身不能去重。
for (i = 0;i <= size - 3;i ++)
{
j = i + 1;
k = size - 1;
if (i > 0 && nums[i] == nums[i - 1])//i更新值不能和之前i相同,i,j不同,数组有序,则k必不同
{
continue;
}
while (j < k)
{
if (nums[j] + nums[k] > nums[i] * (-1))
{
k --;
}
else if (nums[j] + nums[k] < nums[i] * (-1))
{
j ++;
}
else if (nums[j] + nums[k] == nums[i] * (-1))
{
printf("%d %d %d\n", nums[i], nums[j], nums[k]);
while (j < k - 1 && nums[j] == nums[j + 1]) //j更新值不能和之前的j相同
{
j ++;
}
j ++;
}
}
}
return 0;
}