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

2023-12-16 04:53:06

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

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)

文章来源:https://blog.csdn.net/Leonardo_t/article/details/134970218
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。