Offer 驾到,掘友接招!我正在参与 2022 春招系列活动-刷题打卡任务,点击查看活动详情。
题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例
示例 1
输入: nums = [-1, 0, 1, 2, -1, -4] 输出: [[-1, -1, 2], [-1, 0, 1]]示例 2
输入: nums = [] 输出: []示例 3:
输入: nums = [0] 输出: []
思路分析(排序 + 双指针)
-
特殊判断:如果数组为
null或者长度小于3,直接返回[] -
对数组排序。因为要三个数相加等于 0,即三个数中一定会区分正负,排序后可以更好的进行数据筛选
-
遍历排序后的数组
-
若
nums[i] > 0, 则直接返回结果: 因为已经排序好,所以后面不可能有三个数加和等于 0。 -
若遇到重复元素,则直接跳过: 避免出现重复解
-
令左指针
left = index + 1,右指针right = len - 1,当left < right时,执行循环:- 当
nums[index] + nums[left] + nums[right] == 0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 left, right 移到下一位置,寻找新的解 - 若 sum > 0,说明 nums[right] 太大,right--
- 若 sum < 0,说明 nums[left] 太小,left++
- 当
-
AC 代码
impl Solution {
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let mut ans = vec![];
let len = nums.len();
// 如果数组为 null 或者长度小于 3,直接返回 []
if len < 3 {
return ans;
}
let mut nums = nums;
// 对数组排序
nums.sort();
let (mut index, mut left, mut right) = (0, 0, 0);
// 遍历排序后的数组
for index in 0..len {
// 若 nums[i] > 0, 则直接返回结果
if nums[index] > 0 {
return ans;
}
// 若遇到重复元素,则直接跳过
if (index > 0) && (nums[index] == nums[index - 1]) {
continue;
}
// 左指针 left = index + 1
left = index + 1;
// 右指针 right = len - 1
right = len - 1;
// 当 left < right 时,执行循环
while left < right {
match nums[index] + nums[left] + nums[right] {
0 => { // 当 nums[index] + nums[left] + nums[right] == 0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 left, right 移到下一位置,寻找新的解
ans.push(vec![nums[index], nums[left], nums[right]]);
left += 1;
right -= 1;
while left < right && nums[left] == nums[left - 1] {
left += 1;
}
while left < right && nums[right] == nums[right + 1] {
right -= 1;
}
},
a if a > 0 => {right -= 1}, // 若 sum > 0,说明 nums[right] 太大,right--
_ => {left += 1}, // 若 sum < 0,说明 nums[left] 太小,left++
}
}
}
ans
}
}
扩展题型
- 数组求和
- 双链表合并