力扣最热一百题——6.三数之和

目录

[题目链接:15. 三数之和 - 力扣(LeetCode)](#题目链接:15. 三数之和 - 力扣(LeetCode))

题目描述

示例

提示

解法一:双指针

代码分析

总结


没啥多说的,就是最近CS根本上不了分谢谢。


题目链接:15. 三数之和 - 力扣(LeetCode)

注:下述题目描述和示例均来自力扣

题目描述

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != 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
  • -10^5 <= nums[i] <= 10^5

解法一:双指针

  1. 排序

    • 首先,将数组 nums 进行排序。这是因为排序可以简化处理逻辑,使得我们可以使用双指针技术来高效地找到三数之和为零的组合。
  2. 遍历和去重

    • 使用一个 for 循环遍历数组 nums。对于每个元素 nums[i],我们尝试找到另外两个元素 nums[left]nums[right],使得它们的和与 nums[i] 的和为零。
    • 在遍历时,首先检查当前元素 nums[i] 是否大于零。如果 nums[i] 大于零,则直接返回结果,因为后面的所有元素也都大于零,不可能再找到和为零的三元组。
    • 为了避免重复的三元组,使用一个去重机制。如果当前元素与前一个元素相同,跳过当前元素。
  3. 双指针查找

    • 初始化两个指针 leftright,分别指向 i 之后的第一个元素和数组的最后一个元素。
    • 进入 while 循环,通过移动 leftright 指针来寻找满足条件的三元组。
      • 如果 nums[i] + nums[left] + nums[right] 大于零,则 right 向左移动以减少总和。
      • 如果小于零,则 left 向右移动以增加总和。
      • 如果等于零,则找到了一个满足条件的三元组,将其加入结果列表中。
  4. 处理重复元素

    • 在找到一个有效三元组后,为了避免结果中出现重复的三元组,需要对 leftright 指针所指向的元素进行去重处理。
    • 移动 left 指针,跳过所有与下一个元素相同的值。
    • 移动 right 指针,跳过所有与上一个元素相同的值。
  5. 返回结果

    • 最终返回存储所有三元组的 result 列表。

代码分析

  • 时间复杂度O(n^2)。排序的时间复杂度是 O(n log n),而双指针查找的时间复杂度是 O(n^2),因为每次内层 while 循环最多遍历整个数组。

  • 空间复杂度O(1)(不包括返回结果空间)。算法只使用了固定数量的额外空间来存储指针和变量。

java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //创建需要返回的集合
        ArrayList<List<Integer>> result = new ArrayList<>();
        //将数组nums进行排序
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            //排序之后如果第一个数已经大于0,则已经不可能使和为0
            if (nums[i] > 0){
                return result;
            }
            //防止重复元素加入,现在进行去重操作
            if (i > 0 && nums[i] == nums[i - 1]){
                //发现为重复元素,跳过这次循环
                continue;
            }
            //定义left和right两个指针
            int left = i + 1;
            int right = nums.length - 1;
            //开始查找合适的集合元素
            while ( left < right){
                if (nums[i] + nums[left] + nums[right] > 0){
                    //大于0,right左移\
                    right--;
                }else if (nums[i] + nums[left] + nums[right] < 0){
                    //小于0,left右移\
                    left++;
                }else {
                    //获得正确目标,将目标加入result集合
                    result.add(Arrays.asList(nums[i] , nums[left] , nums[right] ));
                    
                    //同时在加入之后防止找到重复的目标,进行while中的去重操作
                    while (left < right && nums[left] == nums[left + 1]){
                        //left重复,将left右移
                        left++;
                    }
                    while (left < right && nums[right] == nums[right - 1]){
                        //right重复,将right左移
                        right--;
                    }
                    //去重操作完毕,将继续while遍历,寻找目标值,移动left和right
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}

总结

多多熟悉就好啦!!!今天也开学了,我也刚发布了一篇图像识别的文章,大家多多支持谢谢!!!!!

链接如下:实时图形识别的实现:模板匹配与几何特征方法的对比-CSDN博客

感谢大家的支持!!!

相关推荐
白榆maple4 分钟前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少9 分钟前
数据结构——线性表与链表
数据结构·c++·算法
sjsjs1115 分钟前
【数据结构-合法括号字符串】【hard】【拼多多面试题】力扣32. 最长有效括号
数据结构·leetcode
此生只爱蛋1 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
程序员勋勋1 小时前
【自动化测试】如何在jenkins中搭建allure
职场和发展·jenkins·测试覆盖率
咕咕吖2 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
九圣残炎2 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu2 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
丫头,冲鸭!!!3 小时前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
Re.不晚3 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea