Day6|454.四数相加II ● 383. 赎金信 ● 15. 三数之和 ● 18. 四数之和

文章探讨了数组中寻找特定和的子集问题,从三数之和的解决方案开始,详细解释了如何使用排序和双指针法有效地找到所有可能的组合。对于存在重复元素的情况,文章强调了剪枝策略的重要性,例如在四数之和的问题中,通过循环和条件判断来避免无效计算。

454.四数相加II

四数相加II
本道题因为不同数组可能存在相同的累加和,所以要用map记录,因为是不同数组挑,所以可以分为两组来解决

383. 赎金信

赎金信

15. 三数之和

三数之和
一个很难想的题目,特别是利用了双指针法这个。
里面还有很多细节
1、排序后第一个大于零后,后面肯定就不满足了
2、由于是不重复的,所以每当收进去一个后,要将重复的元素跳过
3、思路就是控制左右指针的移动,大了右指针左移,小了左值针右移。

func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    res := [][]int{}
    for i:= 0; i < len(nums); i++{
        if nums[i] > 0{
            return res
        }
        if i >0 && nums[i] == nums[i-1]{
            continue 
        }
        left := i + 1
        right := len(nums) - 1
        for left < right{
            if nums[i] + nums[left] + nums[right] < 0{
                left++
            }else if nums[i] + nums[left] + nums[right] > 0{
                right--
            }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] == nums[right - 1]{
                    right--
                }
                left++
                right--
            }
        }
        
    }
    return res
}

18. 四数之和

四数之和
这道题目和三数之和的想法一样,只不过是多了一层循环嵌套在最外面
主要是分析他的减枝思路:
第一层循环里

// 剪枝处理
            if (nums[k] > target && nums[k] >= 0) {
            	break; // 这里使用break,统一通过最后的return返回
            }

第二层循环里剪枝

for (int i = k + 1; i < nums.size(); i++) {
                // 2级剪枝处理
                if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
                    break;
                }

因为是四个元素,所以并不是首元素大于目标值就满足条件,必须还得是大于0.

func fourSum(nums []int, target int) [][]int {
    ret := make([][]int, 0)
    sort.Ints(nums)

    for i := 0; i < len(nums); i++{
        if i > 0 && nums[i - 1] == nums[i]{
            continue
        }
        for j := i + 1; j < len(nums); j++{
            if j > i + 1 && nums[j - 1] == nums[j]{
            continue
            }
            left := j + 1
            right := len(nums) - 1
            for left < right{
                sum := nums[i] + nums[j] + nums[left] + nums[right]
                if sum < target{
                    left++
                }else if sum > target{
                    right--
                }else{
                    ret = append(ret,[]int{nums[i] , nums[j] , nums[left] , nums[right]})
                    for left < right && nums[left] == nums[left + 1]{
                        left++
                    }
                    for left < right && nums[right] == nums[right - 1]{
                        right--
                    }
                    left++
                    right--
                }
            }
        }
    }
    return ret
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值