015 三数之和

题目

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

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

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

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

实现

第一种:利用 排序 + 三索引 的方法

为了避免三次循环,提升执行效率。首先,对nums进行排序。然后,固定3个索引i,l(left),r(right)i进行最外层循环,l指向nums[i]之后数组的最小值,r指向nums[i]之后数组的最大值。模仿快速排序的思路,如果nums[i] > 0就不需要继续计算了,否则计算nums[i] + nums[l] + nums[r]是否等于零并进行相应的处理。如果大于零,向l方向移动r指针,如果小于零,向r方向移动l索引,如果等于零,则加入到存储最后结果的result链表中。当然,题目中要求这个三元组不可重复,所以在进行的过程中加入去重就好。

C# 实现

  • 执行结果:通过
  • 执行用时:348 ms, 在所有 C# 提交中击败了 99.54% 的用户
  • 内存消耗:35.8 MB, 在所有 C# 提交中击败了 6.63% 的用户
public class Solution 
{
    public IList<IList<int>> ThreeSum(int[] nums) 
    {
        IList<IList<int>> result = new List<IList<int>>();

        nums = nums.OrderBy(a => a).ToArray();
        int len = nums.Length;
        
        for (int i = 0; i < len - 2; i++)
        {
            if (nums[i] > 0) 
                break; // 如果最小的数字大于0, 后面的操作已经没有意义

            if (i > 0 && nums[i - 1] == nums[i])
                continue; // 跳过三元组中第一个元素的重复数据

            int l = i + 1;
            int r = len - 1;

            while (l < r)
            {
                int sum = nums[i] + nums[l] + nums[r];
                if (sum < 0)
                {
                    l++;
                }
                else if (sum > 0)
                {
                    r--;
                }
                else
                {
                    result.Add(new List<int>() {nums[i], nums[l], nums[r]});
                    // 跳过三元组中第二个元素的重复数据
                    while (l < r && nums[l] == nums[l + 1]) 
                    {
                        l++;
                    }
                    // 跳过三元组中第三个元素的重复数据
                    while (l < r && nums[r - 1] == nums[r]) 
                    {
                        r--;
                    }
                    l++;
                    r--;
                }
            }
        }
        return result;    
    }
}

Python 实现

  • 执行结果:通过
  • 执行用时:660 ms, 在所有 Python3 提交中击败了 95.64% 的用户
  • 内存消耗:16.1 MB, 在所有 Python3 提交中击败了 75.29% 的用户
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums = sorted(nums)

        result = []

        for i in range(0, len(nums) - 2):
            # 如果最小的数字大于0, 后面的操作已经没有意义
            if nums[i] > 0:
                break
            # 跳过三元组中第一个元素的重复数据
            if i > 0 and nums[i-1] == nums[i]:
                continue
            
            # 限制nums[i]是三元组中最小的元素
            l = i + 1
            r = len(nums) - 1            
            while l < r:
                sum = nums[i] + nums[l] + nums[r]
                if sum < 0:
                    l += 1
                elif sum > 0:
                    r -= 1
                else:
                    result.append([nums[i], nums[l], nums[r]])
                    # 跳过三元组中第二个元素的重复数据
                    while l < r and nums[l] == nums[l+1]:
                        l += 1
                    # 跳过三元组中第三个元素的重复数据
                    while l < r and nums[r] == nums[r-1]:
                        r -= 1                    
                    l += 1
                    r -= 1
        return result
浙ICP备19012682号