代码如下
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
}