代码随想录复习 454 四数相加 15 三数之和 18 四数之和

文章提供了两个Go语言函数,分别用于解决15题的三数之和问题和18题的四数之和问题。这两个函数通过排序数组和双重/三重循环来找到满足条件的数之和,利用哈希表优化了查找效率。对于四数之和,函数首先检查数组长度,然后对数组排序,使用双指针法遍历寻找满足条件的组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码如下 

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {

             m := make(map[int]int)    //思路如下 假设四个数组为A,B,C,D 。A数组里的元素为a 以此类推  若要四数之和相加等于0 ,先统计a+b的值,假设 0-(c+d) = a+b  ,那么如果a+b存在,且-(c+d)也存在,那么这四个数相加就是0 

            

             for _,v1 := range nums1 {

                 for _,v2 := range nums2 {

                     m[v1+v2]++  //这里就是统计a+b存在的个数

                 }

             }

             count := 0 

             for _,v3 := range nums3 {

                for _,v4 := range nums4 {

                    count += m[-v3-v4]      //如果-c-d存在,因为-c-d = a+b 所以直接将结果计算进去。举例 如果 a+b = 5 ,-(c+d)= 5 ,那么最后的结果就是a+b的个数 ,如果a+b没有对应的-(c+d)存在,那么他的个数则为0 

                }

             }

             return count

}

15 三数之和 

代码如下 

func threeSum(nums []int) [][]int {

        sort.Ints(nums)  //将数组排序

        res := [][]int{}  //声明一个结果数组

        for i := 0 ; i < len(nums)-2 ; i++ {  //遍历这个数组,因为是三数之和,所以定义一个i作为第一个数

              n1 := nums[i]  //将第一个数设置为n1 

              if n1 > 0 {  //因为是排序过得数组,所以如果n1大于0 ,那么后面的数字肯定都大于0 ,所以肯定不符合结果,终止循环

                  break 

              }

              if i > 0 && n1 == nums[i-1] {  如果这个数和前一个数相同,说明这个数的结果前一个数字都遍历过了,所以需要跳过这个数 

                  continue 

              }

              left,right := i+1,len(nums)-1   //将第二个数定义为left,第三个数定义为right 。第二个数是第一个数的后一个,第三个数是数组的最后一个数

              for left < right { 遍历这个left,right区间 

                  n2,n3 := nums[left],nums[right] //将这两个数定义为n2和n3 

                  if n1+n2+n3 == 0 {  //如果这三个数相加等于0 ,说明符合结果,添加到结果数组中 

                      res = append(res,[]int{n1,n2,n3})

                  

                  for left < right && nums[left] == n2 {  //如果在这个区间里面,有一个数字等于之前定义的第二个数字,就需要将这个数字跳过 。直到不等于这个n2.并进行下一次的循环,并将这个数定义为新的第二个数进行遍历 

                      left++ 

                  }

                  for left < right && nums[right] == n3 {

                      right--                    //同理跳过第三个数字 

                     }

                  }else if n1+n2+n3 < 0 { //如果三数之和小于0 ,则说明需要增加数的大小,因为第一个数固定,第三个数已经是数组里的最大的数,所以需要将第二个数变大

                      left++

                  }else {  //同理如果三数之和大于0 则需要减小数的大小,所以把第三个数变小  

                      right--

                  }

              }

        }

        return res 

}

18 四数之和 

代码如下 

func fourSum(nums []int, target int) [][]int {

         if len(nums) < 4 {  如果这个数组个数小于四个直接返回

             return nil 

         }

         sort.Ints(nums)  对数组进行排序

         res := [][]int{} 定义一个结果数组 

         for i := 0 ; i < len(nums)-3 ; i++ {  遍历第一个数

             if nums[i] > target && nums[i] > 0 && target > 0 {  如果这个数字大于 目标值,并且目标值和这个数都是大于0 的那么直接终止循环,因为后面的都是正数,只会越加越大

                 break 

             }

             n1 := nums[i]   将第一个数定义为n1 

             if i > 0 && n1 == nums[i-1] { 如果当前这个数,前面的数已经和这个数相等了,那么就需要跳过这个数 

                 continue 

             }

             for j := i + 1 ; j < len(nums)-2 ; j++ {  遍历第二个数 

                 n2 := nums[j] 将第二个数定义为n2 

                 if j > i+1 && n2 == nums[j-1] {  同理,如果前面的数和这个数相等需要跳过这个数 

                     continue

                 }

                 left := j+1   //第三个数的起始位置是第二个数的后一个

                 right := len(nums)-1  //第四个数的起始位置数组最后一个数

                 for left < right { 遍历第三个数到第四个数的区间 

                     n3 := nums[left] 将n3定义为第三个数

                     n4 := nums[right] 将n4定义为第四个数 

                     sum := n1+n2+n3+n4  sum定义为四数之和 

                     if sum < target { 如果这个和小了,就加大第三个数

                         left++

                     }else if sum > target { 如果和大了就减小第四个数 

                         right--

                     }else {

                         res = append(res,[]int{n1,n2,n3,n4})  符合的话,放入结果

                         for left < right && n3 == nums[left+1] {  如果当前这个数和后一个数相同,则将指针移动到下一个位置,直到当前这个数和后一个数不同,这样做的目的是可以去除和n3相同的数

                             left++

                         }

                         for left < right && n4 == nums[right-1] {

                             right--

                         }

                         left++  将双指针移动一位进行下次遍历 

                         right--

                     }

                 }

             }

             

         }

         return res 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值