leetcode之15三数之和Golang
题目的要求有两个,首先是三个数的和为0,其次是这种和为0的三元组不能重复。
当给定一个数组,我们求满足和为0的三元组的时候核心思想使用的是暴力破解,也就是三重循环,遍历三次数组,但是在这里我们给出如下优化:
首先将数组按照从小到大的顺序排序
设置三个指针index,分别为i,j,k,他们分别代表数组中满足上述三元组条件的数的位置。
然后使用指针i进行第一次遍历,找出第一个数,这层遍历有如下的限制:
如果当前的数与前一个数的大小相等,那么我们可以直接跳过当前的数,因为这个数字已经被处理过了(这就是我们前面排序的好处,可以快速去除重复)
当指定了第一个数以后,后两个数的和也就唯一确定了,因为三个数的和为0
然后我们的第二次优化就是将寻找第二个数和第三个数的循环合并成一个循环,这就使得算法的时间复杂度降低了一个数量级
寻找第二个数是从第一个数的下一位开始,第三个数是从数组的末尾开始,直到指向第二个数和第三个数的指针相遇,就退出循环(这也是前面对数组进行排序的好处),因此这一层循环的时间复杂度是O(n)。
寻找第二个数和第三个数的另一个限制就是去除重复数字,和第一个数字一样,如果遍历到的当前数字和上一个遍历的数字一样,那么这个数字就不做处理。
代码如下:
func threeSum(nums []int) [][]int {
resArr := make([][]int, 0)
sort.Ints(nums)
for i := 0; i < len(nums); i++ {
if i-1 >= 0 && nums[i-1] == nums[i] {
continue
}
for j, k := i+1, len(nums)-1; j < len(nums) && k > j; {
if j >= i+2 && nums[j-1] == nums[j] {
j++
continue
}
if k < len(nums)-1 && nums[k] == nums[k+1] {
k--
continue
}
sum := nums[i] + nums[j] + nums[k]
if sum == 0 {
tmpArr := make([]int, 3)
tmpArr[0] = nums[i]
tmpArr[1] = nums[j]
tmpArr[2] = nums[k]
resArr = append(resArr, tmpArr)
j++
k--
continue
} else if sum > 0 {
k--
continue
} else {
j++
continue
}
}
}
return resArr
}
浙公网安备 33010602011771号