美文网首页
15. 3Sum 三数相加

15. 3Sum 三数相加

作者: sarto | 来源:发表于2022-03-16 14:23 被阅读0次

题目

给定一个整数数组 nums,找到所有的 i,j,k 游标,使得三个数相加等于 0。

解析

该问题借鉴 两数相加。我们首先要知道所有的两数相加之和,然后才能根据 map 来确定第三个数是否存在。

  1. 我们划定一个 map[int]int 其 key 为数值,value 为坐标 i。
  2. 用两个指针,一前一后,分别为 j,k 。首先 j=0,k=i+1 判断 nums[i] + nums[j] 取反是否在 map 中
  3. 如果存在,是一种解法
  4. 当 k 移动完成后,如果 i 值不存在 map,将 i 值写入 map 中。

一些复杂的情况:

  1. 在判断 num[j] + num[k] 时,如何去除重复
    重复发生在两种情况中
    (1) j 固定不变时,第一次出现合适的值,后续出现相同的值
    (2) j 移动变化后,后续重复的问题

乱序去重代价过大。考虑对数组进行排序。

排序解析

排序后我们固定第一个数为 num[i],然后在剩下数字两端分别为 num[j] num[k]
计算 num[i] + num[j] + num[k] 的关系。
如果相等,说明是一种解法,此时我们同时 j++ k--,如果解法和上一个相同,重复,继续步进
这里同时步进是没有问题的,因为两个数固定的话,另一个数要满足条件一定是固定的。

如果 num[i] + num[j]+num[k] < 0 ,移动 j,如果 > 0 移动 k
重复这个过程。

一些重复情况

  1. [-1,0,0,1,1] 当 i = 0, j =1, k = 4 时,和为 0 此时,我们分别移动 j 和 k。但是 j 和 k 和以前的值一样,发生了重复,我们需要去除这个重复情况。即重复发生时 nums[j] == nums[j-1] && nums[k] = nums[k+1] 注意临界条件,j != i+1 && k != len(nums) -1
    为了书写代码方便,我们可以将逻辑转换为什么时候是不重复,可以作为结果。当sum 为 0 时。
    (1) 如果 j 位于左边界,一定不重复
    (2) 如果 k 位于右边界,一定不重复
    (3) 如果 nums[j] != nums[j-1] 一定不重复
    (4) 如果 nums[k] != nums[k+1] 一定不重复
if j == i+1 || k == len(nums)-1 || nums[j] != nums[j-1] || nums[k] != nums[k+1] {
  rst = append(rst,[]int{nums[i],nums[j],nums[k]})
}
  1. [-1,-1,-1, 0,1]
    当 i = 0 时,我们得到 [-1,0,1] 此时,我们应该将 i 指针移动到下一个不等于 -1 的数,以避免后续再次匹配到相同的结果
for i<len(nums)-2
  if nums[i] == nums[i+1]
    i+=1

伪码

sort(nums)

for i=0; i< len(s); i++
  for j=i+1,k=len(s); j<k;
    sum = nums[i] + num[j] + nums[k]
    if sum == 0
      if notDup
        rst += {i,j,k}
    if sum < 0
        j++
    if sum > 0
        k--
   i = nextNotEqual(i)

代码

func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    var rst [][]int
    for i:=0; i<len(nums)-2; i++ {
        j:=i+1
        k:=len(nums)-1
        for ; j<k;{
            sum := nums[i]+nums[j]+nums[k]
            switch {
            case sum==0:
                if j == i+1 || k == len(nums)-1 || nums[j] != nums[j-1] || nums[k] != nums[k+1] {
                    rst = append(rst, []int{nums[i],nums[j],nums[k]})
                }
                j++
                k--
            case sum<0:
                j++
            case sum>0:
                k--
            }
        }
        if nums[i] > 0 {
            break
        }
        for ; i<len(nums)-2; {
            if nums[i] == nums[i+1] {
                i++
            } else {
                break
            }
        }
    }
    return rst
}

相关文章

网友评论

      本文标题:15. 3Sum 三数相加

      本文链接:https://www.haomeiwen.com/subject/rfzudrtx.html