leetcode 15. 三数之和(3Sum)

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

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

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

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

 

原题链接

 

思路:

这题可以使用哈希表,我这里没用,用的算是三指针,从小到大排好后,当第一个指针都大于0了,那3个指针的值加起来不可能等于0了,此时break,为了不重复,最内层的while 实现了排重

 

 

class Solution {
    
    public List<List<Integer>> threeSum(int[] nums) {
    	List<List<Integer>> ans = new ArrayList<>();
    	Arrays.sort(nums);
    	
    	
    	for(int k=0;k<nums.length - 1;k++)
    	{
    		if(nums[k]>0)
    			break;
    		if(k>0 && nums[k]==nums[k-1])
    			continue;
    		
    		int l = k+1;
    		int r = nums.length - 1;
    		int target = 0 - nums[k];
    		while(l<r)
    		{
    	    	List<Integer> list = new ArrayList<>();
                while(l+1<r && nums[l+1]==nums[l])
    				l++;
    			while(l+1<r && nums[r-1]==nums[r])
    				r--;    	    
    			if(nums[l] + nums[r] == target)
    			{
    				list.add(nums[k]);
    				list.add(nums[l]);
    				list.add(nums[r]);
    				ans.add(list);

    				l++;
    				r--;
    			}
    			else if(nums[l] + nums[r] < target)
    				l++;
    			else
    				r--;
    		}
    	}
    	
		return ans;
        
    }
}

 

 

附上 beat 100% 的代码

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
      if (nums.length < 3)
        return Collections.emptyList();
      List<List<Integer>> res = new ArrayList<>();
      int minValue = Integer.MAX_VALUE;
      int maxValue = Integer.MIN_VALUE;
      int negSize = 0;
      int posSize = 0;
      int zeroSize = 0;
      for (int v : nums) {
        if (v < minValue)
          minValue = v;
        if (v > maxValue)
          maxValue = v;
        if (v > 0)
          posSize++;
        else if (v < 0)
          negSize++;
        else
          zeroSize++;
      }
      if (zeroSize >= 3)
        res.add(Arrays.asList(0, 0, 0));
      if (negSize == 0 || posSize == 0)
        return res;
      if (minValue * 2 + maxValue > 0)
        maxValue = -minValue * 2;
      else if (maxValue * 2 + minValue < 0)
        minValue = -maxValue * 2;

      int[] map = new int[maxValue - minValue + 1];
      int[] negs = new int[negSize];
      int[] poses = new int[posSize];
      negSize = 0;
      posSize = 0;
      for (int v : nums) {
        if (v >= minValue && v <= maxValue) {
          if (map[v - minValue]++ == 0) {
            if (v > 0)
              poses[posSize++] = v;
            else if (v < 0)
              negs[negSize++] = v;
          }
        }
      }
      Arrays.sort(poses, 0, posSize);
      Arrays.sort(negs, 0, negSize);
      int basej = 0;
      for (int i = negSize - 1; i >= 0; i--) {
        int nv = negs[i];
        int minp = (-nv) >>> 1;
        while (basej < posSize && poses[basej] < minp)
          basej++;
        for (int j = basej; j < posSize; j++) {
          int pv = poses[j];
          int cv = 0 - nv - pv;
          if (cv >= nv && cv <= pv) {
            if (cv == nv) {
              if (map[nv - minValue] > 1)
                res.add(Arrays.asList(nv, nv, pv));
            } else if (cv == pv) {
              if (map[pv - minValue] > 1)
                res.add(Arrays.asList(nv, pv, pv));
            } else {
              if (map[cv - minValue] > 0)
                res.add(Arrays.asList(nv, cv, pv));
            }
          } else if (cv < nv)
            break;
        }
      }
      return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值