22年35周

目录

一:四数相加Ⅱ

二:赎金信

三:三数之和

四:四数之和


一:四数相加Ⅱ

题目链接:四数相加Ⅱ

思路:这道题本来是没啥思路的,只想到了四重循环,但是有感觉不太现实,所以看了看答案,答案用hash表的方式,把四重循环转换为二重循环了,其实这是一个挺好的思路,以后就要记住这个思路。

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
    hashTable := make(map[int]int)
    count := 0
    for _,v1 := range nums1{
        for _,v2 := range nums2{
            hashTable[v1+v2]++
        }
    } 

    for _,v3 := range nums3{
        for _,v4 := range nums4{
            count += hashTable[-v3-v4]
        }
    }
    return count 
}

二:赎金信

题目链接:赎金信

思路:这道题思路就比较正常了,就是用hash表完成的,先将magazine里面的字符拆解出来,存到hash表中,最后遍历另一个字符串然后对hash表进行减法操作。

func canConstruct(ransomNote string, magazine string) bool {

    hashTable := make(map[rune]int)

    for _,v := range magazine {
        hashTable[v]++
    }

    for _,v := range ransomNote {
        hashTable[v]--

        if hashTable[v] < 0 {
            return false
        }
    }

    return true
}

三:三数之和

题目链接:三数之和

思路:先进行排序,再利用双指针法查找相加数组为0的组合,这道题的难点在于怎么样去去重,去除重复的数组。

import "sort"

func threeSum(nums []int) [][]int {

    sort.Ints(nums)

    results := make([][]int,0)
    
    length := len(nums)

    for i:=0;i<length-2; {

        left := i+1
        right := length-1

        for left < right {
            if nums[i] + nums[left] + nums[right] == 0 {
                results = append(results,[]int{nums[i] , nums[left] , nums[right]})

                n1,n2 := nums[left] ,nums[right]

                for left<right && n1 == nums[left]{ //在内层循环,双指针之间的进行去重,如果相等就跳过这次查找
                    left++
                }

                for left<right && n2 == nums[right]{
                    right--
                }

                continue
            }
            if nums[i] + nums[left] + nums[right] > 0 {
                right--
                continue
            }
            left++
        } 
       
        n3 := nums[i]
        i++
        for i < length - 2 && nums[i] == n3 {//外层循环,如果第一层就重复了,则直接跳过
                                               //关键点:要这个外层数据使用完之后再去重,不要直接上来就去重
            i++
        } 
    }
    return results

}

这道题大家也很容易想到利用回溯法,回溯法可以剪枝操作去重,但是回溯法是超时的。代码如下:

var res [][]int
func threeSum(nums []int) [][]int {
    res = make([][]int,0)
    sort.Ints(nums)
    traceBack(nums,[]int{},3,0)
    return res
}

func traceBack(nums []int,path []int,n int,sum int) {

    if n ==0 && sum == 0 {
        temp := make([]int,len(path))
        copy(temp,path)
        res = append(res,temp)
        return
    }
    if n < 0 {
        return
    }

    for i:=0;i<len(nums);i++ {
        //去重
        if i>0 && nums[i-1] == nums[i] {
            continue
        }
        path = append(path,nums[i])
        traceBack(nums[i+1:],path,n-1,sum+nums[i])
        path = path[:len(path)-1]
    }

}

 

四:四数之和

题目链接:四数之和

思路:和三数之和一样的道理,只是多了一层循环,这里用到双指针所作的优化是把O(n4)的复杂度优化成了O(n3),三数之和同理。

import "sort"

func fourSum(nums []int, target int) [][]int {

    sort.Ints(nums)
    length := len(nums)
    results := make([][]int,0)

    for i:=0;i<length - 3; {
        for j:=i+1;j<length - 2; {

            left := j+1
            right := length-1

            for left < right {
                if nums[i] + nums[j] + nums[left] + nums[right] == target {
                    results = append(results,[]int{nums[i],nums[j],nums[left],nums[right]})
                    n1,n2 := nums[left],nums[right]

                    for left<right && n1 == nums[left] {
                        left++
                    }

                    for left<right && n2 == nums[right] {
                        right--
                    }
                    continue
                }

                if nums[i] + nums[j] + nums[left] + nums[right] < target {
                    left++
                }
                if nums[i] + nums[j] + nums[left] + nums[right] > target {
                    right--
                }

            }
            n3 := nums[j]
            j++
            for j < length-2 && n3 == nums[j] {
                j++
            }
        }
        n4 := nums[i]
        i++
        for i < length-3 && n4 == nums[i] {
            i++
        }
        
    }
    return results
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值