(本合集全部为Go语言实现)
Leetcode454
状态:秒了
实现过程中的难点:思想就是利用哈希表将部分和记录下来,最终实现将n ^ 4
转换为2 * n ^ 2
个人写法
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
note := make(map[int]int)
for _, i := range nums1 {
for _, j := range nums2 {
note[i + j]++
}
}
res := 0
for _, i := range nums3 {
for _, j := range nums4 {
res += note[-(i + j)]
}
}
return res
}
Leetcode383
状态:秒了
实现过程中的难点:跟字母异位词
差不多
个人写法
func canConstruct(ransomNote string, magazine string) bool {
note := make([]int, 26)
for _, c := range magazine {
note[c - 'a']++
}
for _, c := range ransomNote {
if (note[c - 'a'] == 0) {
return false
}
note[c - 'a']--
}
return true
}
Leetcodexxx
状态:卡了挺长时间的,主要是想用个Set
但是Go没有内置的实现,也没有想到其实不用去重就可以保证结果集内的元素不重复
实现过程中的难点:着重是要想明白怎么操作才能使结果集不需要去重
关键点
需要首先明确是,一定是需要先排序,再把问题化简成
两数之和
的处理方式
- 为什么想到可能有重复?
- 首先参数的数字集合中会有重复,那么在遍历的时候,就有可能出现对于单个循环来说,两次进入循环时为同一个值,此时就有会出现结果集元素的重复
- 如何解决?
- 首先想到的就是在进入循环时,判断是否和上一次循环的值相同,但是又有另一个疑问
- 如果本来结果集的元素内部就有相同的值,如
[2, -1, -1]
,那么对于第二个-1
,会不会因为进入循环时的判断而跳过这个结果?- 不会。对于上述的结果集元素样式,第二个
-1
再首次取该值时,是和前一个元素判断的,也就是循环一定是取的最左层的-1
,此时第三个元素也会在循环内部取到-1
,因而不会导致跳过
- 不会。对于上述的结果集元素样式,第二个
个人写法
主体结构可以不包括代码中的
if-break
判断,这些都是剪枝的判断,可以降低代码执行时间
import "sort"
func threeSum(nums []int) [][]int {
sort.Ints(nums)
res := make([][]int, 0)
if nums[len(nums) - 1] < 0 {
return res
}
for i := 0; i < len(nums); i++ {
if nums[i] > 0 {
break
}
if i > 0 && nums[i] == nums[i - 1] {
continue
}
j, k := i + 1, len(nums) - 1
for j < k {
if nums[i] + nums[j] > 0 || nums[k] < 0 {
break
}
if j > i + 1 && nums[j] == nums[j - 1] {
j++
continue
}
curRes := nums[i] + nums[j] + nums[k]
if curRes > 0 {
k--
} else if curRes < 0 {
j++
} else {
res = append(res, []int {nums[i], nums[j], nums[k]})
j++
k--
}
}
}
return res
}
Leetcode18
状态:卡了一下,和上一题还是有区别的,主要是在目标值是0还是其他数的区别上
实现过程中的难点:实现上本质上还是在上一题的基础上套了一层。但目标值可能不是零,如果是0️,那么可以按上一题的一些判断一样进行剪枝,但是如果不是0,那么即使前几个数比目标值小,也可能因为后续几个数的相加而变大,因为后续的数也可能是正数,反之亦然
个人写法
import "sort"
func fourSum(nums []int, target int) [][]int {
sort.Ints(nums)
res := make([][]int, 0)
for i := range nums {
if i > 0 && nums[i] == nums[i - 1] {
continue
}
for j := i + 1; j < len(nums); j++ {
cur2 := nums[i] + nums[j]
if j > i + 1 && nums[j] == nums[j - 1] {
continue
}
m, n := j + 1, len(nums) - 1
for m < n {
cur3 := cur2 + nums[m]
if m > j + 1 && nums[m] == nums[m - 1] {
m++
continue
}
curRes := cur3 + nums[n]
if curRes > target {
n--
} else if curRes < target {
m++
} else {
res = append(res, []int {nums[i], nums[j], nums[m], nums[n]})
m++
n--
}
}
}
}
return res
}
今日收获
- 复习了几数之和系列,有一些思想如果不写一些确实比较难想到
学习时长:3小时左右