leetcode15 3Sum

题目内容

Given an array nums of n integers, are there elements a, b, c in nums such that a + 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.

Example:
Given array nums = [-1, 0, 1, 2, -1, -4],

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

分析过程

  • 题目归类:
    数组,遍历,hashmap

  • 题目分析:
    上一篇博客采用hashmap解决了two sum的问题。类似的本题可以采用two sum的方式完成,固定第一个值x,此时另外两个值的和为 0-x;

  • 边界分析:

    • 空值分析
      nums为空返回空
    • 循环边界分析
      循环变量不可以大于nums.length;
  • 方法分析:

    • 数据结构分析
      hashmap,hashmap 的key保存具体数值,value保存index。
      在比较的时候需要设立一个变量保存index,相同的数值,不同index才能使用。

      补充:根据two sum 的方法,当出现两个相同的数和一个其他数相加为0时,会出现重复的情况。例如:[-1,1,0],[-1,-1,2],[0,-1,1]。用这种方法需要去重,
      去重方法;使用hashset就可以判断重复的情况,之前以为hashset中的arraylist是保存的数据的引用,所以new新的arraylist就无法去重。现在看来hashset中equals是通过判断每一个list中的hashcode。
    public int hashCode() {
        int hashCode = 1;
        for (E e : this)//E 为List<E>,this为需要添加的对象(String/ArrayList)
            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
        return hashCode;
    }
    
    • 状态机
    • 状态转移方程
    • 最优解
  • 测试用例构建
    [1,2,3,-1,-2,-3,0],
    []

代码实现

import java.util.*;
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        HashSet<List<Integer>> set = new HashSet<List<Integer>>();
        List<Integer> tmpList ;
        for(int i = 0;i < nums.length; i++){
            HashMap<Integer,Integer> map = new HashMap<>();
            int target = 0 - nums[i];
            for(int j = i+1; j < nums.length;j++){
                int value = target - nums[j];
                if(map.containsKey(value)){
                    tmpList = new ArrayList<Integer>();
                    tmpList.add(nums[i]);
                    tmpList.add(nums[j]);
                    tmpList.add(value);
                    Collections.sort(tmpList);
                    set.add(tmpList);
                    
                }else{
                    map.put(nums[j],j);
                }
                
            }
        }
        return new ArrayList<List<Integer>>(set);
    }
}

效率提高


由图可知效率不高。
学习到另外一种方式可以有效的降低时间复杂度。
首先先排序。
设置一个i,j,k,分别为不同的下标。i的值不能大于nums.length-2; j 的值不能大于nums.length-1, k的值不小于等于j
和之前一样,先固定i的值。之后nums[i],nums[j],nums[k]之和如果大于0,k--,反之j++,当j>=k时break;

import java.util.*;
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        HashSet<List<Integer>> set = new HashSet<List<Integer>>();
        Arrays.sort(nums);
        for(int i = 0; i < nums.length-2;i++){
            int j = i+1;
            int k = nums.length-1;
            while(j<k){
                int sum =nums[i]+nums[j]+nums[k];
                if(sum==0)
                    set.add(Arrays.asList(nums[i],nums[j++],nums[k--]));
                else if(sum>0)
                    k--;
                else if(sum<0)
                    j++;
            }
        }
        return new ArrayList<List<Integer>>(set);
    }
}

效率依旧不高,但是使用的方法可以借鉴。

拓展问题

3Sum Closest
4Sum
3Sum Smaller

原文地址:https://www.cnblogs.com/clnsx/p/12240564.html