回溯问题-LeetCode39-组合总和

一、回溯

回溯法的思想是:通过枚举,对所有的可能进行遍历。但是枚举是一直枚举到最后一个元素,发现走不通,再回退一步,枚举没有走过的元素。回溯的关键在于:走不通就回退一步。

回溯的实现:for循环+递归

解释如下:for循环就像一个路径选择,递归返回之后就相当于回退一步。例如第一次选择第一条路径,i = 0,进入该条路径,递归方法完成后返回,相当于回退到初始点,然后进入下一次循环。

二、回溯模板

public backward(){
    if(回退点){
        //这条路的结束点
        save();
        return;
    }else{
        //剪枝
        if(不满足){
           return; 
        }else{
            //从当前路径开始,继续遍历下一个元素
            dfs(...);
        } 
    }  
}

三、组合总和

1、所有元素都可以被无限使用,则每次递归都要从当前元素开始寻找路径

    for(int i = curIndex; i < candidates.length; i++)

2、单条路径的实现:new ArrayList<Integer>(),作为dfs的参数进入递归,每次递归结束后进行回溯操作

3、代码部分

import java.util.ArrayList;
import java.util.List;


public class CombinationSum {

    public static List<List<Integer>> res;
    public static void main(String[] args) {
        System.out.println(combinationSum(new int[]{2,3,6,7},7));
    }


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

    public static void dfs(int[] candidates,int target,int index,List<Integer> list){
        if(target == 0){
            res.add(new ArrayList<>(list));
            return;
        }
        if(target < 0){
            return;
        }
        for(int i = index; i < candidates.length; i++){
            list.add(candidates[i]);
            dfs(candidates,target - candidates[i],i,list);
            list.remove(list.size()-1);
        }
    }
}

4、dfs优化

如果在进入递归前就能判断当前路走不通,就减少了递归调用dfs次数,减少运行时间。

public static void dfs(int[] candidates,int target,int index,List<Integer> list){
        if(target == 0){
            res.add(new ArrayList<>(list));
            return;
        }

        for(int i = index; i < candidates.length; i++){
            if(target - candidates[i] < 0) break;
            list.add(candidates[i]);
            dfs(candidates,target - candidates[i],i,list);
            list.remove(list.size()-1);
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值