15. 三数之和

74 阅读1分钟

Problem: 15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。

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

思路:双指针

求出来三元组简单,难的是去重。可以把问题变成一层循环+二数之和

双指针去重的思路就是循环遍历前后两个指针,如果挪动相加值不变就继续移动指针

外层循环的去重思路是: 判断第一层循环的指针i和第二个指针j的距离,如果大于1而且i+1 = i,这是时候说明i+1其实是没用的,可以直接把指针i挪一位到i+1

Code

func threeSum(nums []int) [][]int {
	// mp := make(map[int]int)
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	res := make([][]int, 0)
	for i := 0; i < len(nums)-2; i++ {

		for j, k := i+1, len(nums)-1; j < k; {

			if nums[i]+nums[j]+nums[k] == 0 {
				res = append(res, []int{nums[i], nums[j], nums[k]})

			}
            // 两数之和去重
			for j < k && nums[i]+nums[j]+nums[k] == 0 {
				// 去重
				for j-i > 1 && i+1 < len(nums) && nums[i] == nums[i+1] {
					i++
				}
			

				j++
			}
			// 从 > 或者 < 到= 这个状态应该记录下来,是一个转折点
            // 所以不能写成 >=
			for j < k && nums[i]+nums[j]+nums[k] == 0 {
				k--
			}
			for j < k && nums[i]+nums[j]+nums[k] > 0 {
				k--
			}
			for j < k && nums[i]+nums[j]+nums[k] < 0 {
				j++
			}
		}
	}

	return res
}