首页 > 其他分享 >15. 三数之和 Golang实现

15. 三数之和 Golang实现

时间:2024-09-13 11:15:06浏览次数:10  
标签:right 15 nums 三数 三元组 Golang 数组 指针 left

给你一个整数数组 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³),不满足题目要求。

  • 从暴力解法到优化
    在暴力解法中,确定了一个数后,剩下两个数的查找可以视为“两数之和”问题。如果我们能通过某种方式快速查找剩下的两个数,就能减少遍历的复杂度。
    常见的两数之和问题可以通过哈希表实现,但这里的关键点是,我们需要找的三元组不仅要和为零,还需要确保不重复,这增加了查找的难度。
  • 引入排序和双指针
    为了降低查找复杂度,我们可以先对数组进行排序。排序有两个好处:
    1.排序后的数组,便于使用双指针技巧快速查找剩余的两个数。
    2.排序可以帮助去除重复的解(因为相同的元素只需要考虑一次)。
  • 固定一个数:遍历数组,固定其中一个数 nums[i]。
    寻找剩下两个数:通过双指针技巧,在剩余部分的数组中寻找和为 -nums[i] 的另外两个数。

  • 双指针的运用
    双指针技巧是指在有序数组中,使用两个指针(通常是头和尾)来进行查找的方式。

假设我们固定了 nums[i],需要在剩下的数组中找到两个数 nums[left] 和 nums[right],使得它们的和为 -nums[i]。
根据双指针的性质:
如果当前的三数之和 nums[i] + nums[left] + nums[right] 小于零,说明我们需要更大的数,于是左指针 left 右移。
如果当前的三数之和大于零,说明我们需要更小的数,于是右指针 right 左移。
如果找到三数之和为零,则保存结果,并同时移动两个指针,继续寻找其他可能的组合。

  • 去重问题
    由于可能存在重复的元素,结果中不能包含重复的三元组。因此,在实现中需要特别处理去重的情况:

遍历时,如果当前元素与前一个元素相同,则直接跳过,避免重复计算。
在找到一个符合条件的三元组后,需要跳过数组中与当前 left 和 right 指针相同的元素,确保不会重复处理相同的组合。

  • 为什么选择双指针?
    时间复杂度的优化:双指针法将暴力求解的复杂度从 O(n³) 降低到 O(n²),这是因为每次外层循环固定一个数时,剩下的部分只需要通过一次双指针查找就可以完成。
    排序的好处:排序虽然需要 O(n log n) 的时间,但在排序后的数组中,双指针法可以有效利用数组的有序性来快速调整查找范围,这使得整体复杂度得到了优化。

  • 总结思路
    最终解决这个问题的思路总结如下:

    排序:首先将数组排序,方便后续查找并去重。
    遍历数组:对于每一个 nums[i],将问题简化为在剩下的数组中寻找两个数使得三数之和为零。
    双指针查找:在有序数组中使用双指针查找,通过移动指针调整和的大小。
    去重处理:确保结果集中不包含重复的三元组,处理遍历中的重复元素。

点击查看代码
func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    var res [][]int
    for i := 0; i < len(nums)-2; i++ {
        if i > 0 && nums[i] == nums[i-1] {
            continue // 去重
        }
        left, right := i + 1, len(nums) - 1
        for left < right {
            sum := nums[i] + nums[left] + nums[right]
            if sum == 0 {
                res = append(res, []int{nums[i], nums[left], nums[right]})
                // 跳过重复的 left 和 right
                for left < right && nums[left] == nums[left+1] {
                    left++
                }
                for left < right && nums[right] == nums[right-1] {
                    right--
                }
                left++  // 更新 left
                right-- // 更新 right
            } else if sum < 0 {
                left++
            } else {
                right--
            }
        }
    }
    return res
}

标签:right,15,nums,三数,三元组,Golang,数组,指针,left
From: https://www.cnblogs.com/CharlseGo/p/18411860

相关文章

  • P3327 [SDOI2015] 约数个数和
    [SDOI2015]约数个数和题目描述设\(d(x)\)为\(x\)的约数个数,给定\(n,m\),求\[\sum_{i=1}^n\sum_{j=1}^md(ij)\]输入格式输入文件包含多组测试数据。第一行,一个整数\(T\),表示测试数据的组数。接下来的\(T\)行,每行两个整数\(n,m\)。输出格式\(T\)行,每行一个整数,表......
  • 基于java的美食信息推荐系统的设计与实现(11315)
     有需要的同学,源代码和配套文档领取,加文章最下方的名片哦一、项目演示项目演示视频二、资料介绍完整源代码(前后端源代码+SQL脚本)配套文档(LW+PPT+开题报告)远程调试控屏包运行三、技术介绍Java语言SSM框架SpringBoot框架Vue框架JSP页面Mysql数据库IDEA/Eclipse开发四、项......
  • golang 中的 sync.WaitGroup
    sync.WaitGroup是Go标准库中的一个同步原语,用于协调多个goroutine的执行,确保它们在主线程或其他goroutine继续执行之前完成任务。sync.WaitGroup的用法1.创建WaitGroup实例在开始goroutine执行之前,需要创建一个WaitGroup实例。这个实例将用于跟踪正在运行的goro......
  • 什么是golang中的channel
    在Go语言中,channel是一种用于在goroutine之间进行通信和同步的工具。它允许一个goroutine发送数据到channel,另一个goroutine从channel接收数据,从而实现并发编程中的数据交换。 Channel的关键特性类型安全:每个channel都有一个指定的类型,确保发送到channel的......
  • Java突击面试八股文(15个技术栈,持续更新中)
    1.Java如何避免死锁注意加锁的顺序,保证每个线程按顺序进行加锁;加锁时限,可以设置一个超时时间;注意死锁检查,这是一种预防机制,可以确保发生死锁的第一时间进行处理。3、多线程(线程池)2线程有哪些状态(生命周期)新建、就绪、运行、阻塞、死亡3如何获取多线程的返回值?深坑!如果......
  • ELK 8.15 启用Fleet Server和安装Agent
    注意,这里的URL,使用端口8220,不是443curl-L-Ohttps://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.15.1-linux-x86_64.tar.gztarxzvfelastic-agent-8.15.1-linux-x86_64.tar.gzcdelastic-agent-8.15.1-linux-x86_64可以将如下这一段存为一个sh文件,......
  • 【力扣16】最接近的三数之和
    16.最接近的三数之和-力扣(LeetCode)接近target:大于或小于两种情况。但是实际操作中只需考虑大于的情况,找到之后结果的前一个数也有可能是结果,进行比较(更新结果res)。第二种情况的实现依靠右指针的移动思路类似15对于每个j,找到一个最小的k,使得满足条件(j变大,k一定减小即k--)......
  • C语言15--联合体与枚举
    联合体(共同体)基本概念        联合体的外在形式跟结构体非常类似,但它们有一个本质的区别:结构体中的各个成员是各自独立的内存空间,而联合体中的各个成员却共用同一块内存,因此联合体也称为共用体。联合体各成员的堆叠效果联合体内部成员的这种特殊的“堆叠”效果,使......
  • Why system logging "kernel: tcp_parse_options: Illegal window scaling value 15 >
    环境Linux问题在var/log/messages文件中发现以下日志。Oct621:01:05mplttaxsx101kernel:tcp_parse_options:Illegalwindowscalingvalue15>14received.Oct621:01:05mplttaxsx101kernel:tcp_parse_options:Illegalwindowscalingvalue15>14......
  • 15_三数之和
    15_三数之和【问题描述】给你一个整数数组nums,判断是否存在三元组[nums[i],nums[j],nums[k]]满足i!=j、i!=k且j!=k,同时还满足nums[i]+nums[j]+nums[k]==0。请你返回所有和为0且不重复的三元组。注意:答案中不可以包含重复的三元组。示例一:输入:nums......