【代码随想录】算法训练计划07

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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不之道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值