基本知识要求:
Java:方法、数组、集合、泛型、if else语句、while循环、Arrays.sort()、Arrays.asList()、逻辑运算符、自增自减运算符
Python: 方法、列表、sort()排序、集合、if else语句、while循环、逻辑运算符
题目:
给你一个整数数组 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
思路解析 :
为了找到所有和为0且不重复的三元组,我们可以首先对数组进行排序,然后使用三个指针(i, j, k)在排序后的数组上进行遍历。
以下是解决这个问题的步骤:
- 对数组
nums
进行排序。 - 遍历数组,使用指针
i
从头开始,表示三元组的第一个元素。 - 为了避免重复,我们需要在遍历过程中跳过所有与
nums[i]
相同的元素,直到找到一个不同的元素。 - 使用指针
j
从i+1
开始,表示三元组的第二个元素。 - 使用指针
k
从数组末尾开始,表示三元组的第三个元素。 - 当
i < j < k
时,进行以下操作:- 如果
nums[i] + nums[j] + nums[k] == 0
,则找到了一个三元组,将其添加到结果集中,并跳过所有与nums[j]
和nums[k]
相同的元素,继续寻找下一个三元组。 - 如果
nums[i] + nums[j] + nums[k] < 0
,则j
需要向右移动以增大和。 - 如果
nums[i] + nums[j] + nums[k] > 0
,则k
需要向左移动以减小和。
- 如果
- 遍历结束后,返回结果集。
Java代码示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
/**
* 找到数组中所有和为0的三元组
*
* @param nums 整数数组
* @return 所有和为0的三元组列表
*/
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>(); // 存储结果的三元组列表
Arrays.sort(nums); // 对数组进行排序,以便使用双指针法
// 遍历数组,i为三元组的第一个元素
for (int i = 0; i < nums.length - 2; i++) {
// 跳过所有与nums[i]相同的元素,避免重复的三元组
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// j为三元组的第二个元素,初始位置为i+1
int j = i + 1;
// k为三元组的第三个元素,初始位置为数组末尾
int k = nums.length - 1;
// 当j < k时,进行内层循环
while (j < k) {
// 计算当前三个元素的和
int sum = nums[i] + nums[j] + nums[k];
if (sum == 0) {
// 如果和为0,则找到一个三元组,添加到结果中
result.add(Arrays.asList(nums[i], nums[j], nums[k]));
// 跳过所有与nums[j]相同的元素
while (j < k && nums[j] == nums[j + 1]) {
j++;
}
// 跳过所有与nums[k]相同的元素
while (j < k && nums[k] == nums[k - 1]) {
k--;
}
// 继续寻找下一个三元组
j++;
k--;
} else if (sum < 0) {
// 如果和小于0,则增加j的值,以增大和
j++;
} else {
// 如果和大于0,则减小k的值,以减小和
k--;
}
}
}
// 返回结果
return result;
}
public static void main(String[] args) {
Solution solution = new Solution();
int[] nums = {-1, 0, 1, 2, -1, -4};
List<List<Integer>> triplets = solution.threeSum(nums);
// 输出所有找到的三元组
for (List<Integer> triplet : triplets) {
System.out.println(triplet);
}
}
}
Python代码示例:
def three_sum(nums):
# 先对数组进行排序
nums.sort()
triplets = []
n = len(nums)
# 遍历数组,从第一个元素开始
for i in range(n - 2):
# 跳过重复的元素
if i > 0 and nums[i] == nums[i - 1]:
continue
# 使用双指针法来寻找剩下的两个数
j = i + 1
k = n - 1
while j < k:
current_sum = nums[i] + nums[j] + nums[k]
if current_sum == 0:
# 找到一个三元组,将其添加到结果中
triplets.append([nums[i], nums[j], nums[k]])
# 跳过所有重复的元素
while j < k and nums[j] == nums[j + 1]:
j += 1
while j < k and nums[k] == nums[k - 1]:
k -= 1
j += 1
k -= 1
elif current_sum < 0:
# 如果和太小,则增加j
j += 1
else:
# 如果和太大,则减小k
k -= 1
return triplets
# 示例
nums = [-1, 0, 1, 2, -1, -4]
print(three_sum(nums))
# 输出:[[-1, -1, 2], [-1, 0, 1]]
这段代码定义了一个名为three_sum
的函数,它接受一个整数数组nums
作为输入,并返回所有和为0的不重复三元组的列表。函数首先对数组进行排序,然后使用三个指针(i
,j
,k
)来遍历数组,并寻找满足条件的三元组。找到后,它使用两个内部循环来跳过所有重复的元素,以避免在结果中包含重复的三元组。最后,它返回找到的所有三元组的列表。