【LeetCode】15. 三数之和(Set用法)

  今日学习的文章链接和视频链接

leetcode题目地址:15. 三数之和

 代码随想录题解地址:代码随想录

题目简介

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

看到题目的第一想法(可以贴代码)

1. 最暴力的解法:对每个元素,求出它与其他所有元素的和,再判断剩余元素里是否contains其和的相反数;至于去重,可以将return的元素存成set,判断每次是否所有元素都在set里了。

        写的好烂,出现各种小bug,甚至难以记录。        //超出时间限制

// 超出时间限制
public List<List<Integer>> threeSum(int[] nums) {
    List<Integer> set = Arrays.stream(nums).boxed().collect(Collectors.toList());
    List<List<Integer>> res = new ArrayList<>();
    Set<Integer> check = new HashSet<>();
    boolean c = false;
    int count = 0;
    for (int i : set){
        if (i == 0) count++;
    }
    if(count >= 3) {
        List<Integer> temp = new ArrayList<>();
        temp.add(0);
        temp.add(0);
        temp.add(0);
        res.add(temp);
    }
    for (int i = 0; i < nums.length; i++){
        for (int j = i + 1; j < nums.length; j++){

            set.remove(Integer.valueOf(nums[i]));
            set.remove(Integer.valueOf(nums[j]));
            if (set.contains(-(nums[i]+nums[j]))){
                List<Integer> temp = new ArrayList<>();
                temp.add(nums[i]);
                temp.add(nums[j]);
                temp.add(-(nums[i]+nums[j]));
                for (List<Integer> lll : res){
                    if (lll.containsAll(temp)){
                        set.add(Integer.valueOf(nums[i]));
                        set.add(Integer.valueOf(nums[j]));
                        c = true;
                        continue;
                    }
                }
                if (c){
                    c = false;
                    continue;
                }
                res.add(temp);
            }
            set.add(Integer.valueOf(nums[i]));
            set.add(Integer.valueOf(nums[j]));
        }
    }
    return res;
}

实现过程中遇到哪些困难

1. List里add的Object,是一个指针?就是会随着Object后续的改变一起改变。

        解决方案:在循环内每次new一个新的实例,每次添加的都是新的实例就行了。

2. 各种小bug....(好像是正常的)

看完代码随想录之后的想法

【解题思路】双指针法 + 排序(去重);就算用双指针法,好像也是用Map?

【想法】

1. 去重不能影响其他指针。

2. 主要还是逻辑没想清楚,建议下次拿出草稿纸好好想想再开始写代码。

看完视频自己写的ACC:

public List<List<Integer>> threeSum(int[] nums) {
    List<List<Integer>> res = new ArrayList<>();
    Arrays.sort(nums);
    int left, right, sum = 0;
    for (int i = 0; i < nums.length - 2; i++){
        if (i > 0 && nums[i] == nums[i-1]) continue;
        left = i + 1;
        right = nums.length - 1;
        while (left < right){
            sum = nums[i] + nums[left] + nums[right];
            if (sum == 0){
                List<Integer> temp = new ArrayList<>();
                temp.add(nums[i]);
                temp.add(nums[left]);
                temp.add(nums[right]);
                res.add(temp);
                while (left < right && nums[left] == nums[left+1]){
                    left++;
                }
                while (left < right && nums[right] == nums[right-1]){
                    right--;
                }
                left++;
                right--;
            }else if (sum < 0){
                left++;
            }else if (sum > 0){
                right--;
            }
        }
    }
    return res;
}

 标答:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
	// 找出a + b + c = 0
        // a = nums[i], b = nums[left], c = nums[right]
        for (int i = 0; i < nums.length; i++) {
	    // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
            if (nums[i] > 0) { 
                return result;
            }

            if (i > 0 && nums[i] == nums[i - 1]) {  // 去重a
                continue;
            }

            int left = i + 1;
            int right = nums.length - 1;
            while (right > left) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum > 0) {
                    right--;
                } else if (sum < 0) {
                    left++;
                } else {
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
		    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    
                    right--; 
                    left++;
                }
            }
        }
        return result;
    }
}

学习时长

9:00 ~ 12:00  解题成功、看视频题解、写博客


今日收获

1. 实现Set的类

2. 双重数组/矩阵初始化

List<List<Integer>> list = new ArrayList<>();

不是:List<List<Integer>> res = new List<List<Integer>>();

3. Set用法

Set<Integer>转int[]
int[] arr = set.stream().mapToInt(Integer::intValue).toArray();
int[]转Set<Integer>
Integer[] arrInteger = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Set<Integer> set = Arrays.stream(arrInteger).collect(Collectors.toSet());

  • add() - 将指定的元素添加到集合中

  • addAll() - 将指定集合的所有元素添加到集合中

  • iterator() -返回一个迭代器,该迭代器可用于顺序访问集合中的元素

  • remove() - 从集合中移除指定的元素

  • removeAll() - 从存在于另一个指定集合中的集合中删除所有元素

  • keepAll()  -保留集合中所有还存在于另一个指定集合中的所有元素

  • clear() - 从集合中删除所有元素

  • size() - 返回集合的长度(元素数)

  • toArray() - 返回包含集合中所有元素的数组

  • contains() -  如果集合包含指定的元素,则返回true

  • containsAll() - 如果集合包含指定集合的所有元素,则返回true

  • hashCode() -返回哈希码值(集合中元素的地址)

  • //基本的数学集合运算

  • Union - 为了得到两个集合x和y的并集,我们可以使用x.addAll(y)

  • Intersection - 要获得两个集合x和y的交集,我们可以使用x.retainAll(y)

  • Subset - 要检查x是否是y的子集,我们可以使用y.containsAll(x)

  • 34
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值