【Leetcode-字符串】组合总和

组合总和
难度:中等
在这里插入图片描述
为了加深对dfs的理解,又找了题来练练手。
同样的思路,运用dfs求解的核心在于两点:
1、找到截止条件
2、找出“候选人”并筛选

这道题的截止条件为数组中的数字总和大于target,而候选人则为candidates数组中的任意元素,因为题干中提到元素可以多次使用,则无筛选条件
代码如下:

	public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();    
        List<Integer> integers = new ArrayList<>();
        dfs(candidates,target,res,integers,0);
        return res;
    }
	/**
     * @param candidates 候选数组
     * @param target     每减去一个元素,目标值变小
     * @param res        结果集列表
     * @param integers	 当前数组
     * @param sum	     当前数组元素总和
     */
    public void dfs(int[] candidates,int target,List<List<Integer>> res,List<Integer> integers,int sum){
        //截止条件
        if (sum>=target){
            if (sum==target){
            	//因为题目中求的是组合,则例如出现{2,2,3}或者{2,3,2}时,应该认为是同一种组合
                List<Integer> tmp = new ArrayList<>(integers);
                Collections.sort(tmp);
                if (!res.contains(tmp)){
                    res.add(tmp);
                }

            }
            return;
        }
		
        for (int i = 0; i < candidates.length; i++) {
        	//通过sum记录当前数组integers中元素的总和
            sum += candidates[i];
            integers.add(candidates[i]);
            dfs(candidates,target,res,integers,sum);
            sum -= candidates[i];
            integers.remove(integers.size()-1);
        }
    }

执行结果:成功
在这里插入图片描述
功能成功实现,但执行用时只击败了5%+的用户,因为递归中出现了很多次不必要的运算.我把优化的点分为以下两个方面:
1、当遍历到数组为{2,2,2,2}时,此时的数组中元素总和已经大于target,所以后续的{2,2,2,3}和{2,2,2,7}没有再遍历的必要。基于这种思路,我们首先需要对传入的数组candidates进行排序,后续判断增加剪枝逻辑
2、当我们的数组candidates排序后,那么也不会出现{2,2,3}和{2,3,2}这种相同的组合了,所以也不需要再判断数组中是否有相同的结果了。

代码如下:

public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();    
        List<Integer> integers = new ArrayList<>();
        Arrays.sort(candidates);
        dfs(candidates,target,res,integers,0,0);
        return res;
    }

	/**
     * @param candidates 候选数组
     * @param target     每减去一个元素,目标值变小
     * @param res        结果集列表
     * @param integers	 当前数组
     * @param sum	     当前数组元素总和
     * @param start      循环遍历起点
     */
    public void dfs(int[] candidates,int target,List<List<Integer>> res,List<Integer> integers,int sum,int start){
        if (sum==target){
            res.add(new ArrayList(integers));
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            sum += candidates[i];
            //剪枝逻辑
            if (sum>target){
                sum -= candidates[i];
                break;
            }
            integers.add(candidates[i]);
            dfs(candidates,target,res,integers,sum,i);
            sum -= candidates[i];
            integers.remove(integers.size()-1);
        }
    }

执行结果:成功
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值