首页 > 其他分享 >【每日一题】[15. 三数之和]

【每日一题】[15. 三数之和]

时间:2023-07-09 09:44:05浏览次数:32  
标签:15 nums ++ 三数 每日 add ans var path

【每日一题】15. 三数之和

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

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

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105
解法一:暴力循环O(n^3)
  • 排序加三重遍历,并添加重复元素限制
  • TLO(Time Limit Out)了
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(nums);
        var n = nums.length;
        for(var i = 0; i < n - 2; i++) {
            if(i > 0 && nums[i] == nums[i-1]) {
                continue;
            }
            for(var j = i + 1; j < n - 1; j++) {
                if(j > i + 1 && nums[j] == nums[j-1]) {
                    continue;
                }
                for(var k = j + 1; k < n; k++) {
                    if(k > j + 1 && nums[k] == nums[k-1]) {
                        continue;
                    }
                    if(nums[i] + nums[j] + nums[k] == 0) {
                        List<Integer> path = new ArrayList<>();
                        path.add(nums[i]);
                        path.add(nums[j]);
                        path.add(nums[k]);
                        ans.add(path);
                    }
                }
            }
        }
        return ans;
    }
}
解法二:双指针优化O(n^2)
  • 先对数组进行升序排序
  • 然后遍历第一个数,则剩下两个数的和要为这个数的负数
  • 双指针设置第一个数后面的位置i+1和最后一个位置r=n-1,如果
    • sum > target,说明和太大,则右指针左移
    • sum < target,说明和太小,则左指针右移
  • 查找三个数一般都可以使用这种双指针进行优化
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(nums);
        var n = nums.length;
        for(var i = 0; i < n; i++) {
            if(i > 0 && nums[i] == nums[i-1]) {
                continue;
            }
            var target = -nums[i];
            var l = i + 1;
            var r = n - 1;
            while(l < r) {
                // System.out.println(i + " " + l + " " + r);
                var sum = nums[l] + nums[r];
                if(sum == target) {
                    List<Integer> path = new ArrayList<>();
                    path.add(nums[i]);
                    path.add(nums[l]);
                    path.add(nums[r]);
                    ans.add(path);
                    while(l < r && nums[l+1] == nums[l]) {
                        l++;
                    }
                    while(r > l && nums[r-1] == nums[r]) {
                        r--;
                    }
                    l++;
                    r--;
                } else if(sum > target) {
                    r--;
                } else {
                    l++;
                }
            } 
        }
        // -4 -1 -1 0 1 2 
        return ans;

    }
}
解法三:哈希优化
  • 同样是使用排序加限定条件防止重复
  • 使用map记录元素的value和下标,然后遍历前两个元素,判断最后一个元素的value是否等于前两个的和的负数并下标在前两个之后即可
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        HashMap<Integer, Integer> map = new HashMap<>();
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            map.put(nums[i], i);
        }
        for (int i = 0; i < n - 1; i++) {
            if (nums[i] > 0) {
                return ans;
            }
            if(i > 0 && nums[i-1] == nums[i]) {
                continue;
            }
            for (int j = i + 1; j < n; j++) {
                if(j > i + 1 && nums[j] == nums[j - 1] || nums[i] + nums[j] > 0) {
                    continue;
                }
                int sum = -nums[i] - nums[j];
                if (map.get(sum) != null && map.get(sum) > j) {
                    List<Integer> dummy = new ArrayList<>();
                    dummy.add(nums[i]);
                    dummy.add(nums[j]);
                    dummy.add(sum);
                    ans.add(dummy);
                }
            }
        }
        return ans;
    }
}

标签:15,nums,++,三数,每日,add,ans,var,path
From: https://www.cnblogs.com/tod4/p/17538338.html

相关文章

  • 【雕爷学编程】Arduino动手做(156)---OTTO两足舵机机器人
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • 15. WWDG配置步骤
    1.WWDG配置步骤2.相关HAL库函数介绍3.编程实战WWDG_HandleTypeDefg_wwdg_handle;/*窗口看门狗初始化函数*/voidwwdg_init(uint8_ttr,uint8_twr,uint32_tfprer){g_wwdg_handle.Instance=WWDG;//寄存器基地址g_wwdg_handle.Init.Counter=tr;/......
  • 「Python实用秘技15」pandas中基于范围条件进行表连接
    本文完整示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/PythonPracticalSkills这是我的系列文章「Python实用秘技」的第15期,本系列立足于笔者日常工作中使用Python积累的心得体会,每一期为大家带来一个几分钟内就可学会的简单小技巧。作为系列第1......
  • 15款最佳的HTML5移动模板
    如果你需要响应式和前端开发,那么HTML5是你务必要学会的Web开发语言。我们在Codecondo上发布的HTML5相关文章依然很受欢迎。例如:为HTML5开发者准备的40个工具、针对HTML5的Web框架,你一定要看看它们,我也相信它们会成为你书签的其中之一。当人们上网搜索登陆页面的时候,他们大多是寻......
  • 一文彻底搞懂MySQL基础:B树和B+树的区别 转载 https://blog.csdn.net/a519640026/arti
    写在前面大家在面试的时候,肯定都会被问到MySql的知识,以下是面试场景:面试官:对于MySQL,你对他索引原理了解吗?我:了解面试官:MySQL的索引是用什么数据机构的?我:B+树面试官:为什么要用B+树,而不是B树?我:…面试官:用B+树作为MySql的索引结构,用什么好处?我:…B树和B+树是MySQL索引使用的数据结构......
  • 每日总结
    7月6日:今天更为深入的学习了大道至简的第四章,让我感觉到了不一样的java,沟通,人与人之间的沟通是必不可少的,我们要合力完成某个项目便需要沟通。开发项目也需要与客户沟通,知道在各个阶段都想干什么,能干什么,而不是一味的埋头。......
  • 闲话 Day15
    这两天的题完全改不动。两个星期之后就NOI了,和现在完全没有的水平形成了鲜明的对比。前两天又去找了点神仙DP做了做。结论是两年白学。题解都看不懂。为什么闲话Day13看的人那么多。是因为我引流了吗。。。然而这个是学术闲话。鉴于没有题材那就整点普及内容吧。......
  • Educational Codeforces Round 151 (Rated for Div. 2) D. Rating System
    贪心由题可得,对于k的选择一定是单调递增的,对于前面选定的k后面选的k必须大于之前选的才会发生新的变化,因此k的选择其实是一个单调栈,由前缀和组成我们要想最后的结果最大,则k值一定要尽可能的高,例如当选中i为k值时,如果从i后面某个原本的前缀和要大于选k之后所得到的前缀和的话,说明......
  • 每日汇报 第二周第六天 JAVA字符串复习和JAVA常用类
    今日所学:把JAVA字符串进行了一下复习;掌握如何创建Integer类、Double类、Boolean类和Character类并熟悉相关的常用方法;理解Number类的“装箱”和“拆箱”过程明日计划:继续学习JAVA常用类遇到困难:练科三等一下午没练上回来还被雨浇透了......
  • Educational Codeforces Round 151 (Rated for Div. 2) C. Strong Password
    题目翻译,给定t组数据,每组数据包含一个字符串s,两个长度为m的字符串l和r,要求判断是否存在一个长度为m的字符串res,满足l[i]<=res[i]<=r[i](i->0~m)且不是s的子序列贪心首先对于所有满足l<res<r的字符串,我们只需判断是否存在一个字符串不是子序列即可,那么我们让res成为子序列的可能......