三数之和

三数之和

CategoryDifficultyLikesDislikes
algorithmsMedium (25.59%)1827-

Tags

array | two-pointers

Companies

adobe | amazon | bloomberg | facebook | microsoft

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 *a,b,c ,*使得 *a + b + c = *0 ?找出所有满足条件且不重复的三元组。

**注意:**答案中不可以包含重复的三元组。

示例:

1
2
3
4
5
6
7
给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

Discussion | Solution

解法

1. 双指针法

  1. 先把数组排序
  2. 从小到大遍历这个数组,每次取一个元素,将这个元素的相反数设为target
  3. 在每次遍历中,使用双指针对当前元素的后面的所有元素进行处理,找到两个元素的和为target,这样,三个元素的和就是 0
  4. 双指针的具体处理方式为:头尾各一个指针,每次判断两个指针所指的元素的和与target的大小,如果和小了,左指针右移;如果和大了,右指针左移,直到两个指针相遇

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
    public List<List<Integer>> threeSum (int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        if (nums.length < 3) {
            return ans;
        }

        Arrays.sort(nums);

        for (int i = 0; i + 2 < nums.length; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue; // skip same result
            }
            int j = i + 1;
            int k = nums.length - 1;
            int target = -nums[i];
            while (j < k) {
                if (nums[j] + nums[k] == target) {
                    ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
                    j++;
                    k--;
                    while (j < k && nums[j] == nums[j - 1]) j++; // skip same result
                    while (j < k && nums[k] == nums[k + 1]) k--; // skip same result
                } else if (nums[j] + nums[k] < target) {
                    j++;
                } else {
                   k--;
                }
            }
        }
        return ans;
    }
}

Rust

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
impl Solution {
    pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
        let len = nums.len();
        if len < 3 {
            return vec![]
        }

        let mut nums = nums;
        nums.sort();

        let mut res: Vec<Vec<i32>> = vec![];
        for i in 0..len-2 {
            if i > 0 && nums[i] == nums[i-1] {
                continue;
            }
            let target = - nums[i];
            let (mut l, mut r) = (i+1, len-1);
            while l < r {
                let s = nums[l] + nums[r]; 
                if s == target {
                    res.push(vec![nums[i], nums[l], nums[r]]);
                    l += 1;
                    r -= 1;
                    while l < r && nums[l] == nums[l-1] {
                        l += 1;
                    }
                    while r > l && nums[r] == nums[r+1] {
                        r -= 1;
                    }
                } else if s < target {
                    l += 1;
                } else {
                    r -= 1;
                }
            }
        }

        res
    }
}
updatedupdated2024-08-252024-08-25