三数之和

102 阅读2分钟

题目来源

3Sum

问题描述

给定一个包含 n 个整数的数组 S,是否存在属于 S 的三个元素 a,b,c 使得 a + b + c = 0 ?找出所有不重复的三个元素组合使三个数的和为零。

注意:结果不能包括重复的三个数的组合。

例如, 给定数组 S = [-1, 0, 1, 2, -1, -4],

一个结果集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

解决方案

python

该方法基于三重遍历,时间复杂度为 O(n3) O ( n 3 ) ,运行超时。
这里写图片描述

class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res=[]
        isin=[]
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                #注意起始遍历位置,代码已经在坐标上去重,但数据还可能重复,故用isin数组辅助记录
                p=-(nums[i]+nums[j])
                if p in nums[j+1:]:
                    t=[nums[i], nums[j], p]
                    t.sort()
                    s="%d%d%d" % (t[0],t[1],t[2])
                    if s not in isin:
                        res.append(t)
                        isin.append(s)
        return res

Java

基于原数组的排序,先固定一个数,然后使用两边夹的办法。该算法时间复杂度为 O(n2) O ( n 2 ) 。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> arrayList=new ArrayList<>();

        Arrays.sort(nums);//排序
        int i,j,k,res;

        for(i=0;i<nums.length-2;i++) {//规定的数从第一个位置开始到倒数第三个
            if(i>0 && nums[i]==nums[i-1])//数组已经有序,避免nums[i]重复
                continue;
            j=i+1;
            k=nums.length-1;
            while (j<k) {//两头夹
                if(j>i+1 && nums[j]==nums[j-1]) {//已经访问过的值不再访问
                    j++;
                    continue;
                }
                if(k<nums.length-1 && nums[k]==nums[k+1]) {//已经访问过的值不再访问
                    k--;
                    continue;
                }

                res=nums[i]+nums[j]+nums[k];
                if (res<0)
                    j++;
                else if (res>0)
                    k--;
                else {
                    arrayList.add(Arrays.asList(nums[i],nums[j],nums[k]));
                    j++;
                    k--;
                }
            }

        }           
        return arrayList;
    }
}

至于是否超时,除了算法的作用外,编程语言也有影响,如下本算法的python代码实现运行超时。

class Solution:
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res=[]
        nums.sort()
        for i in range(len(nums)-2):
            if i>0 and nums[i]==nums[i-1]:
                continue
            j=i+1
            k=len(nums)-1
            while j<k:
                if j>i+1 and nums[j]==nums[j-1]:
                    j+=1
                    continue
                if  k<len(nums)-1 and nums[k]==nums[k+1]:
                    k-=1
                    continue
                s=nums[i] + nums[j] + nums[k]
                if s<0:
                    j+=1
                elif s>0:
                    k-=1
                else:
                    res.append([nums[i],nums[j],nums[k]])
                    j+=1
                    k-=1
        return res