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,第一个数一定是负数,第三个数一定是正数。
题解
rust
impl Solution {
pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
let n = nums.len();
nums.sort();
let mut ans = Vec::new();
(0..n).for_each(|f| {
if f == 0 || nums[f] != nums[f - 1] {
let mut t = n - 1;
let target = -nums[f];
for s in f + 1..n {
if s == f + 1 || nums[s] != nums[s - 1] {
while s < t && nums[s] + nums[t] > target {
t -= 1;
}
if s == t {
break;
}
if nums[s] + nums[t] == target {
ans.push(vec![nums[f], nums[s], nums[t]]);
}
}
}
}
});
return ans;
}
}
go
func threeSum(nums []int) [][]int {
n := len(nums)
sort.Ints(nums)
ans := make([][]int, 0)
for f := 0; f < n; f++ {
if f > 0 && nums[f] == nums[f-1] {
continue
}
t := n - 1
target := -1 * nums[f]
for s := f + 1; s < n; s++ {
if s > f+1 && nums[s] == nums[s-1] {
continue
}
for s < t && nums[s]+nums[t] > target {
t--
}
if s == t {
break
}
if nums[s]+nums[t] == target {
ans = append(ans, []int{
nums[f], nums[s], nums[t]})
}
}
}
return ans
}
c++
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
for (int f = 0; f < n; ++f) {
if (f > 0 && nums[f] == nums[f - 1]) {
continue;
}
int t = n - 1;
int target = -nums[f];
for (int s = f + 1; s < n; ++s) {
if (s > f + 1 && nums[s] == nums[s - 1]) {
continue;
}
while (s < t && nums[s] + nums[t] > target) {
--t;
}
if (s == t) {
break;
}
if (nums[s] + nums[t] == target) {
ans.push_back({
nums[f], nums[s], nums[t]});
}
}
}
return ans;
}
};
java
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<List<Integer>>();
for (int f = 0; f < n; ++f) {
if (f > 0 && nums[f] == nums[f - 1]) {
continue;
}
int t = n - 1;
int target = -nums[f];
for (int s = f + 1; s < n; ++s) {
if (s > f + 1 && nums[s] == nums[s - 1]) {
continue;
}
while (s < t && nums[s] + nums[t] > target) {
--t;
}
if (s == t) {
break;
}
if (nums[s] + nums[t] == target) {
List<Integer> list = new ArrayList<Integer>();
list.add(nums[f]);
list.add(nums[s]);
list.add(nums[t]);
ans.add(list);
}
}
}
return ans;
}
}
typescript
function threeSum(nums: number[]): number[][] {
const n = nums.length;
nums.sort((a, b) => a - b);
const ans: number[][] = [];
for (let f = 0; f < nums.length; ++f) {
if (f > 0 && nums[f] === nums[f - 1]) {
continue;
}
let t = n - 1;
const target = -nums[f];
for (let s = f + 1; s < n; ++s) {
if (s > f + 1 && nums[s] == nums[s - 1]) {
continue;
}
while (s < t && nums[s] + nums[t] > target) {
--t;
}
if (s == t) {
break;
}
if (nums[s] + nums[t] == target) {
ans.push([nums[f], nums[s], nums[t]]);
}
}
}
return ans;
};
python
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = list()
for f in range(n):
if f > 0 and nums[f] == nums[f - 1]:
continue
t = n - 1
target = -nums[f]
for s in range(f + 1, n):
if s > f + 1 and nums[s] == nums[s - 1]:
continue
while s < t and nums[s] + nums[t] > target:
t -= 1
if s == t:
break
if nums[s] + nums[t] == target:
ans.append([nums[f], nums[s], nums[t]])
return ans
非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://developer.aliyun.com/profile/sqd6avc7qgj7y 博客原创~