不忘初心,砥砺前行
作者 | 陌无崖
转载请联系授权
题目
题目来源于leetcode官方网站
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a b c = 0 ?找出所有满足条件且不重复的三元组。 答案中不可以包含重复的三元组 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [[-1, 0, 1],[-1, -1, 2]]
问题
什么情况下三个数相加才会等于零
三个数中肯定有正数和负数。
什么情况下三个数相加不可能为零
如果在一组数据中最小的两个数相加为正数,则这两个数和后面的数相加不可能等于零 如果在一组数据中最小的数为正数,则该数和其它数字相加不可能等于零
怎样判断会出现重复的值
如果在一组数据中有两个数相等,则会出现重复的值
解决思路
在上面的问题中,我们可以提取出几个关键字,如最小、正数、负数、相等;那么我们如何在一组数据中直观的看到这些关键词所对应的数字呢?其实可以轻易的想到,那就是从小到大排序,这样一来我们就很轻易的对负数和正数进行划分,相等的数据也会是相邻的状态,三个数相加等于零一定是负数【左边】的数据和正数【右边】的数据选择三个才能相加等于零。
代码思路
1、首先我们需要排序 2、循环我们的数据 3、如果最小的数大于0直接结束循环 4、如果相邻的数据相等则跳过循环,避免重复 5、如果三个数相加等于零则存储到相应的二维数组中
上面的简单思路有一点我们需要注意,就是这三个数该怎么找,我们说3个数必须是有正数和负 数,那么我们可以有一种办法每次找数相加时,第三个数是从正数中挑选最大的,如果结果仍然为正数,说明正数太大,应该选择一个小的,即排好序的数组倒数第二个数据,以此类推,相反,如果结果为负数,说明负数应该往右边继续寻找。因此我们可以定义两个指针,即下标,对应最左和最右的数据
代码实现
代码语言:javascript复制func threeSum(nums []int) [][]int {
if len(nums) < 3 {
return [][]int{}
}
// 排序
sort.Ints(nums)
fmt.Println(nums)
// 创建一个二维数组
ret := make([][]int, 0, 0)
for i := 0; i < len(nums); i = i 1 {
if nums[i] > 0 {
break
}
if i > 0 && nums[i] == nums[i-1] {
continue
}
// 左右指针指向数组的两端
l := i 1
r := len(nums) - 1
for l < r {
sum := nums[i] nums[l] nums[r]
if sum == 0 {
ret = append(ret, []int{nums[i], nums[l], nums[r]})
for l < r && nums[l] == nums[l 1] {
fmt.Println(nums[l], " ", nums[l 1])
l
}
for l < r && nums[r] == nums[r-1] {
r--
}
l
r--
} else if sum > 0 {
r--
} else if sum < 0 {
l
}
}
}
return ret
}
END
今日推荐阅读
RabbitMQ系列笔记广播模式和路由模式 RabbitMQ系列笔记入门篇
RabbitMQ系列笔记work模式
RabbitMQ系列笔记work模式
protoc语法详解及结合grpc定义服务
Golang中Model的使用
基于Nginx和Consul构建高可用及自动发现的Docker服务架构
▼关注我,一起成长
主要分享 学习心得、笔记、随笔▼