算法训练营day6(补),哈希表2
昨天三数之和未做出来,今天补发
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
map1 := make(map[int]int)
count := 0
// 遍历大nums1和大nums1数组,统计两个数组元素之和,和出现的次数,放到map中
for _, v := range nums1 {
for _, v1 := range nums2 {
map1[v+v1]++
}
}
// 在遍历大nums3和大nums4数组,找到如果 0-(v+v1) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
for _, v := range nums3 {
for _, v1 := range nums4 {
target := 0 - (v + v1)
_, ok := map1[target]
if ok {
count = count + map1[target]
}
}
}
return count
}
//原理和有效字母异位词相似
func canConstruct(ransomNote string, magazine string) bool {
nums := make([]int, 26)
r := ransomNote
m := magazine
if len(r) > len(m) {
return false
}
for i := 0; i < len(m); i++ {
// 通过nums数据记录 magazine里各个字符出现次数
index := int(m[i])
nums[index-97]++
}
for j := 0; j < len(r); j++ {
// 遍历ransomNote,在nums里对应的字符个数做--操作
index := int(r[j])
nums[index-97]--
// 如果小于零说明ransomNote里出现的字符,magazine没有
if nums[index-97] < 0 {
return false
}
}
return true
}
func threeSum(nums []int) [][]int {
size := len(nums)
if size < 3 {
return nil
}
//先对数组进行排序
sort.Ints(nums)
result := [][]int{}
for i := 0; i < size-2; i++ {
n1 := nums[i]
//剪枝处理, 因为n1>0加上任何数都比0大直接跳过
if n1 > 0 {
break
}
//去除重复元素
if i > 0 && n1 == nums[i-1] {
continue
}
left := i + 1
right := size - 1
// 因为元素不能重叠,所以left < right
for left < right {
n2 := nums[left]
n3 := nums[right]
res := n1 + n2 + n3
// res==0找到对应元素放到二维数组里
if res == 0 {
result = append(result, []int{n1, n2, n3})
//再度去重,注意是for千万别写成if,否则会有遗漏
for left < right && n2 == nums[left] {
left++
}
for left < right && n3 == nums[right] {
right--
}
//找不到左右收缩指针
} else if res > 0 {
right--
} else {
left++
}
}
}
return result
}
func fourSum(nums []int, target int) [][]int {
size := len(nums)
if size < 4 {
return nil
}
//先对数组进行排序
sort.Ints(nums)
result := [][]int{}
for i := 0; i < size-3; i++ {
n1 := nums[i]
//第一层剪枝处理,因为target是变量去考虑target<0的情况
if n1 > target && n1 >= 0 {
break
}
//去除重复元素
if i > 0 && n1 == nums[i-1] {
continue
}
//降维处理,把4数之和降位3数和,就可以按照3数之和逻辑处理
for j := i + 1; j < size; j++ {
n2 := nums[j]
//第二层剪枝处理,因为target是变量去考虑target<0的情况
if n2+n1 > target && n2+n1 >= 0 {
break
}
//去除重复元素
if j > i+1 && n2 == nums[j-1] {
continue
}
left := j + 1
right := size - 1
// 因为元素不能重叠,所以left < right
for left < right {
n3 := nums[left]
n4 := nums[right]
res := n1 + n2 + n3 + n4
// res==0找到对应元素放到二维数组里
if res == target {
result = append(result, []int{n1, n2, n3, n4})
//再度去重,注意是for千万别写成if,否则会有遗漏
for left < right && n3 == nums[left] {
left++
}
for left < right && n4 == nums[right] {
right--
}
//找不到左右收缩指针
} else if res > target {
right--
} else {
left++
}
}
}
}
return result
}