您现在的位置是:首页 >技术教程 >【leetcode hot 100】【8】15. 三数之和网站首页技术教程
【leetcode hot 100】【8】15. 三数之和
简介【leetcode hot 100】【8】15. 三数之和
题目
给你一个整数数组 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,则将这个三元组加入结果集中;
- 如果和小于0,则将左指针向右移动一位;
- 如果和大于0,则将右指针向左移动一位;
- 重复步骤3-6,直到左右指针相遇。
代码
c++
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res; // 结果集
int n = nums.size();
sort(nums.begin(), nums.end()); // 对数组进行排序
for (int i = 0; i < n - 2; ++i) { // 遍历数组
if (i > 0 && nums[i] == nums[i - 1]) continue; // 跳过重复的元素
int target = -nums[i]; // 目标值
int left = i + 1; // 左指针
int right = n - 1; // 右指针
while (left < right) { // 使用双指针法查找满足条件的两个数字
int sum = nums[left] + nums[right]; // 当前三个数字的和
if (sum == target) { // 和等于目标值
res.push_back({nums[i], nums[left], nums[right]}); // 加入结果集
++left;
--right;
while (left < right && nums[left] == nums[left - 1]) ++left; // 跳过重复的元素
while (left < right && nums[right] == nums[right + 1]) --right; // 跳过重复的元素
} else if (sum < target) { // 和小于目标值,左指针向右移动
++left;
} else { // 和大于目标值,右指针向左移动
--right;
}
}
}
return res;
}
};
golang
func threeSum(nums []int) [][]int {
var res [][]int
n := len(nums)
sort.Ints(nums) // 对数组进行排序
for i := 0; i < n-2; i++ { // 遍历数组
if i > 0 && nums[i] == nums[i-1] {
continue // 跳过重复的元素
}
target := -nums[i] // 目标值
left := i + 1 // 左指针
right := n - 1 // 右指针
for left < right { // 使用双指针法查找满足条件的两个数字
sum := nums[left] + nums[right] // 当前三个数字的和
if sum == target { // 和等于目标值
res = append(res, []int{nums[i], nums[left], nums[right]}) // 加入结果集
left++
right--
for left < right && nums[left] == nums[left-1] { // 跳过重复的元素
left++
}
for left < right && nums[right] == nums[right+1] { // 跳过重复的元素
right--
}
} else if sum < target { // 和小于目标值,左指针向右移动
left++
} else { // 和大于目标值,右指针向左移动
right--
}
}
}
return res
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。