【每日一题-leetcode】15.three sum

15.三数之和

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

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

示例:

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

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

1.暴力求解

thinking:通过三层loop 这里如果使用ArrryList 是有序 可重复,不能避免元素重复问题。但是使用

LikedHashSet就可以避免元素重复问题

时间复杂度:O(n^3)

public List<List<Integer>> threeSum(int[] nums) {
       if(nums == null || nums.length <=2){
           return Collections.emptyList();
       }
​
       Arrays.sort(nums);
​
       Set<List<Integer>> result = new LinkedHashSet<>();
       for(int i=0;i<nums.length;i++){
           for(int j=i+1;j<nums.length;j++){
               for(int k = j+1;k<nums.length;k++){
                   if(nums[i]+nums[j]+nums[k] == 0){
                       List<Integer> list = Arrays.asList(nums[i],nums[j],nums[k]);
                       result.add(list);
                   }
               }
           }
       }
       return new ArrayList(result);
}

2.哈希表

/**
    * hash slow
    * 1406 ms   46 MB
    *
    * @param nums
    * @return
    */
private List<List<Integer>> hashSolution(int[] nums) {
    if (nums == null || nums.length <= 2) {
        return Collections.emptyList();
    }
    Set<List<Integer>> result = new LinkedHashSet<>();
​
    for (int i = 0; i < nums.length - 2; i++) {
        int target = -nums[i];
        Map<Integer, Integer> hashMap = new HashMap<>(nums.length - i);
        for (int j = i + 1; j < nums.length; j++) {
            int v = target - nums[j];
            Integer exist = hashMap.get(v);
            if (exist != null) {
                List<Integer> list = Arrays.asList(nums[i], exist, nums[j]);
                list.sort(Comparator.naturalOrder());
                result.add(list);
            } else {
                hashMap.put(nums[j], nums[j]);
            }
        }
    }
​
    return new ArrayList<>(result);
}

3.夹逼法

thingking:左右夹逼,三数求和 a+b+c = 0 等价于 a+b=c 将数组进行排序,将c固定 a设置到c的下一个问题,也就是head b设置到最后一个位置 tail位置。

第一次遍历c固定 head 和tail 分别向中间移动,判断如果-sum < target 说明值大 因为是负数。所以tail 左移动,否则就是head右移动。如此一轮后 如果找不到,接着c++ head 和tail接着判断。

就可以找到。时间复杂度相对于上面两种是比较低的。

时间复杂度:O(n)

public List<List<Integer>> threeSum(int[] nums) {
        if (nums.length == 0 || nums.length <=2){
            return Collections.emptyList();
        }

        //元素去重
        Set<List<Integer>> result = new LinkedHashSet<>();

        //排序
        Arrays.sort(nums);

        for (int i = 0; i < nums.length-2; i++) {
            int head = i+1;//左端
            int tail = nums.length-1;//右端
            while (head<tail){
                int sum = -(nums[head]+nums[tail]);//取负值
                if (sum == nums[i]){
                    List<Integer> list = 			Arrays.asList(nums[i],nums[head],nums[tail]);
                    result.add(list);
                }
                if(sum<=nums[i]){
                    tail--;
                }else {
                    head++;
                }
            }
        }
        return new ArrayList<>(result);
    }
发布了270 篇原创文章 · 获赞 350 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/jia970426/article/details/105071816