【一次过】Lintcode 57. 三数之和

本文介绍了解决三数之和问题的两种方法。一种是通过深度优先搜索(DFS)递归求解,另一种则是采用排序加双指针的技术来提高效率。在解决过程中,特别注意去除重复解的情况。

给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。

样例

例1:

输入:[2,7,11,15]
输出:[]

例2:

输入:[-1,0,1,2,-1,-4]
输出:[[-1, 0, 1],[-1, -1, 2]]

注意事项

在三元组(a, b, c),要求a <= b <= c。

结果不能包含重复的三元组。


解题思路1:

Lintcode 153. 数字组合 II类似

public class Solution {
    /**
     * @param numbers: Give an array numbers of n integer
     * @return: Find all unique triplets in the array which gives the sum of zero.
     */
    public List<List<Integer>> threeSum(int[] numbers) {
        // write your code here
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(numbers);
        dfs(numbers, new ArrayList<Integer>(), res, 0);
        
        return res;
    }
    
    private void dfs(int[] a, List<Integer> list, List<List<Integer>> res, int index){
        if(list.size() == 3){
            int tmp = 0;
            for(int i=0; i<list.size(); i++)
                tmp += list.get(i);
            if(tmp == 0){
                res.add(new ArrayList<Integer>(list));
            }
                
            return;
        }
        
        for(int i = index; i < a.length; i++){
            if(i != index && a[i] == a[i-1])
                continue;
            
            list.add(a[i]);
            dfs(a, list, res, i + 1);
            list.remove(list.size() - 1);
        }
    }
}

二刷:

public class Solution {
    /**
     * @param numbers: Give an array numbers of n integer
     * @return: Find all unique triplets in the array which gives the sum of zero.
     */
    public List<List<Integer>> threeSum(int[] numbers) {
        // write your code here
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(numbers);
        
        dfs(numbers, new ArrayList<Integer>(), 0, res, 0);
        
        return res;
    }
    
    private void dfs(int[] numbers, List<Integer> list, int sum, List<List<Integer>> res, int index){
        if(list.size() == 3){
            if(sum == 0)
                res.add(new ArrayList<Integer>(list));
            
            return;
        }
        
        for(int i=index; i<numbers.length; i++){
            if(i != index && numbers[i] == numbers[i-1])
                continue;
            
            list.add(numbers[i]);
            dfs(numbers, list, sum+numbers[i], res, i+1);
            list.remove(list.size()-1);
        }
    }
}

解题思路2:

看到三数之和就想起可以利用两数之和,也就是先遍历元素k,然后在k之后寻找两数之和等于-nums[k]即可,所以可以对数组先排序,然后使用双指针的方式找到两数之和,时间复杂度O(nlogn)。

注意由于题目中不允许出现重复的结果,所以对这三个元素都需要去重,即遇到相同元素跳过。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        
        for(int k=0; k<nums.length-2; k++){
            //剔除掉重复的k
            if(k > 0 && nums[k] == nums[k-1])
                continue;
            
            //two sum
            int target = -nums[k];
            int i=k+1, j=nums.length-1;
            while(i < j){
                if(nums[i] + nums[j] == target){
                    List<Integer> temp = new ArrayList<>();
                    temp.add(nums[k]);
                    temp.add(nums[i]);
                    temp.add(nums[j]);
                    res.add(temp);
                    i++;
                    //剔除掉重复的i
                    while(i < j && nums[i] == nums[i-1])
                        i++;
                    j--;
                    //剔除掉重复的j
                    while(i < j && nums[j] == nums[j+1])
                        j--; 
                }else if(nums[i] + nums[j] < target)
                    i++;
                else
                    j--;
            }
        }

        return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值