1、454. 四数相加 II
题目:
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
思路:
- 哈希+分组+target+判断这个值存在不
- 分成两组,同样的判断存在不存在
- 自己造一个 target
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
// 代码一刷,分成两组,同样的判断存在不存在,时间复杂度 on方
map1 := make(map[int]int, 0)
res := 0
for _,v := range nums1 {
for _,v2 := range nums2 {
map1[v+v2]++
}
}
for _,v := range nums3 {
for _,v2 := range nums4 {
target := 0-(v+v2)
if map1[target] > 0 {
res += map1[target]
}
}
}
return res
}
2、383. 赎金信
题目:
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
输入:ransomNote = “aa”, magazine = “aab”
输出:true
思路:
- 和四数相加2一样,就是元素加进map,判断两个map中含有这个没
- 这题的话,就是判断条件变了一点,就是 >
func canConstruct(ransomNote string, magazine string) bool {
// 代码一刷
map1 := make(map[rune]int, 0)
map2 := make(map[rune]int, 0)
for _,v := range ransomNote {
map1[v]++
}
for _,v := range magazine {
map2[v]++
}
for k,v := range map1 {
if v > map2[k] {
return false
}
}
return true
}
3、15. 三数之和
题目:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
思路:
- i + 双指针,哈希去重太麻烦
- 去重,一定要是 nums[i] 和 i-1 比较,因为前边有 left 啊
- i<len(nums)-2
- if 满足条件后,需要left++,right–以及两个去重,放在满足的条件里边,因为不满足的话,在大于或者等于时候已经+±-过了
- 要使用 n3 避免数组越界
- 去重也不是去一次
func threeSum(nums []int) [][]int {
// 哈希去重很麻烦,用双指针+i
res := make([][]int, 0)
sort.Ints(nums)
for i:=0; i<len(nums)-2; i++ {
if nums[i] > 0 { break }
if i >= 1 {
if nums[i] == nums[i-1] { continue } // 对 i 去重
}
left, right := i+1, len(nums)-1
for left < right {
n3 := nums[right]
if nums[i]+nums[left]+nums[right] > 0 {
right--
} else if nums[i]+nums[left]+nums[right] < 0 {
left++
} else {
res = append(res, []int{nums[i], nums[left], nums[right]})
for left < right && nums[left] == nums[left-1] { left++ } // 去重,去重也不是去一次
for left < right && nums[right] == n3 { right-- } // 去重
}
}
}
return res
}
4、18. 四数之和
题目:
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
思路:
- 和三数之和一样的思路,多个for循环,k,i
- 不要忘记排序
- 看题意,是大于 target
- 不做剪枝也没事,别剪枝剪过头了
func fourSum(nums []int, target int) [][]int {
sort.Ints(nums)
res := make([][]int, 0)
for k:=0; k<len(nums)-3; k++ {
//if nums[k] > 0 && target > 0 && nums[k] >= target { return res } // 一级剪枝
if k>0 && nums[k] == nums[k-1] { continue } // 一级去重
for i:=k+1; i<len(nums)-2; i++ {
//if nums[k]+nums[i] > 0 && target > 0 && nums[k]+nums[i] >= target { return res } // 二级剪枝
if i > k+1 && nums[i] == nums[i-1] { continue } // 二级去重
left, right := i+1, len(nums)-1
for left < right {
if nums[k]+nums[i]+nums[left]+nums[right] > target {
right--
} else if nums[k]+nums[i]+nums[left]+nums[right] < target {
left++
} else {
res = append(res, []int{nums[k],nums[i],nums[left],nums[right]})
n3 := nums[left]
n4 := nums[right]
left++
right--
for left<right && nums[left] == n3 { left++ }
for left<right && nums[right] == n4 { right-- }
}
}
}
}
return res
}