【Leetcode】3Sum - 【两个指针】

15. 3Sum

  • Total Accepted: 127471
  • Total Submissions: 659843
  • Difficulty: Medium

Given an array S of n integers, are there elements a,b,c inS such thata +b +c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

我的代码:(暴力)

目前问题:没有解决重复问题。

public class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        if(nums == null) return null;
        ArrayList<Integer> res ;
        List<List<Integer>> result = new ArrayList<List<Integer>>();

        for(int i = 0 ; i < nums.length ; i++)
            for(int j = 0 ; j < nums.length ; j++)
                for(int k = 0 ; k < nums.length ; k++ )
                    if(nums[i]+nums[j]+nums[k] == 0 && i != j && j != k && i != k ){
                        res = new ArrayList<Integer>();
                        res.add(nums[i]);
                        res.add(nums[j]);
                        res.add(nums[k]);
                        result.add(res);
                    }
         return result;       
    }
}

分析:时间复杂度为O(n3)。



代码(二)(目前运行时长25ms)

代码思路:http://www.cnblogs.com/ganganloveu/p/3832180.html

先升序排序,然后用第一重for循环确定第一个数字。

然后在第二重循环里,第二、第三个数字分别从两端往中间扫。

如果三个数的sum等于0,得到一组解。

如果三个数的sum小于0,说明需要增大,所以第二个数往右移。

如果三个数的sum大于0,说明需要减小,所以第三个数往左移。

时间复杂度:O(n2)

注意:

1、排序之后天然满足non-descending order的要求

2、为了避免重复,在没有空间要求情况下可以用map,但是也可以跳过重复元素来做

import java.util.ArrayList;
import java.util.Collections;   
import java.util.List;


public class Solution {  
    public List<List<Integer>> threeSum(int[] nums) {
        List<Integer> tmp_nums = new ArrayList<Integer>();  
        ArrayList<Integer> res ;  
        List<List<Integer>> result = new ArrayList<List<Integer>>();  
        
        if(nums.length < 3) return result;
        
        for(int i = 0 ; i < nums.length ; i ++){  
            tmp_nums.add(nums[i]);  
        }  
        Collections.sort(tmp_nums);  

        for (int i = 0; i < tmp_nums.size(); ++i) {
            while (i > 0 && i < tmp_nums.size() && tmp_nums.get(i) == tmp_nums.get(i-1) ){
                i++;
            }
            int j = i + 1;
            int k = tmp_nums.size() - 1;
            while (j < k ) {
                if (tmp_nums.get(i) + tmp_nums.get(j) + tmp_nums.get(k) == 0) {
                    res = new ArrayList<Integer>();
                    res.add(tmp_nums.get(i));
                    res.add(tmp_nums.get(j));
                    res.add(tmp_nums.get(k));
                    result.add(res);
                    j++;
                    k--;
                    while (j < k && tmp_nums.get(j) == tmp_nums.get(j - 1))
                        j++;
                    while (k > j && tmp_nums.get(k) == tmp_nums.get(k + 1))
                        k--;
                } else if (tmp_nums.get(i) + tmp_nums.get(j) + tmp_nums.get(k) < 0) {
                    j++;
                    while (j < k && tmp_nums.get(j) == tmp_nums.get(j - 1))
                        j++;
                } else if (tmp_nums.get(i) + tmp_nums.get(j) + tmp_nums.get(k) > 0) {
                    k--;
                    while (k > j && tmp_nums.get(k) == tmp_nums.get(k + 1))
                        k--;
                }
            }

        }  
        return result;  
    }  
}

分析:跳过重复元素很重要,注意边界值判断。要记得一开始判断空。时间复杂度O(n)。但是目前此方法运行很慢。

311 / 311 test cases passed.
 Status:
Accepted
Runtime: 26 ms
Submitted: 0 minutes ago

代码3:

vector<vector<int> > threeSum(vector<int> &num) {
    vector<vector<int> > vvi;
    if (num.size() < 3) return vvi;
    std::sort(num.begin(), num.end(), [] (int a, int b) {return a < b;});
    int f, s, t;
    for (f = 0; f < num.size()-2; ++f) {
        if (f > 0 && num[f] == num[f-1])
            continue;
        for (s = f + 1; s < num.size() - 1; ++s) {
            if (s != f+1 && num[s] == num[s-1])
                continue;
            t = s + 1;
            while (num[f]+num[s]+num[t] <= 0) {
                if (num[f]+num[s]+num[t] == 0) {
                    vector<int> vi;
                    vi.push_back(num[f]);
                    vi.push_back(num[s]);
                    vi.push_back(num[t]);
                    vvi.push_back(vi);
                    break;
                } else if (t < num.size() - 1) {
                    t++;
                } else {
                    break;
                }

            }
        }
    }
    return vvi;
}

分析:代码易懂。但是时间复杂度O(n3)。相当于是解决了重复问题的暴力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值