Java-算法-回溯<一>

下文承接

Java-算法-回溯<二>

一. 简单介绍

1. 回溯算法简单介绍

        回溯算法是基于递归函数之上的,本质是穷举所有可能符合答案的选项。和一般递归最大的区别是,本身带有撤销这一明显特征,即选择,递归,然后返回,撤销。虽然可以加一些剪枝的操作,但本身算法时间复杂度很高,没有改变穷举的本质。

        回溯算法主要解决排列,组合,子集类的问题 [1]。

2. 回溯算法一般模板

public void dfs(参数1,参数2,...,参数n){

    //终止条件
        if(){
        //添加答案
        return;
    }

    //遍历所有可能选项
    for(int i = ?; i < ?; i++){
        //添加操作
        dfs()
        //撤回操作,和有可能的第二次dfs()
        dfs()
    }

}

 3. 回溯算法的树型转换

        回溯算法可以用树来转换,树的深度遍历即DFS可以理解为向下的递归,for循环内可以理解为对所有的可能性的排查,是对本层的遍历。

        以leetcode77中为例,那么对数型结构的转换为:

 以树形结构来思考,可以更具体地抽象出递归的过程,也会方便剪枝。

二. leetcode实战

1. leetcode 77 组合

        给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。

输入:n = 4, k = 2
输出:
[
  [2,4],[3,4], [2,3],[1,2], [1,3],[1,4],
]

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    public List<List<Integer>> combine(int n, int k) {
        List<Integer> path = new ArrayList<>();
        dfs(1,n,k,path);
        return ans;
    }
    public void dfs(int index, int n, int k , List<Integer> path){
        if(path.size() == k){
            ans.add(new ArrayList<Integer>(path));
            return;
        }
        for(int i = index; i <= n; i++){
            path.add(i);
            dfs(i+1, n , k, path);
            path.remove(path.size() - 1);
        }
    }
}

本题小结:

        本题是经典的回溯问题,要注意的点有:(1)ans.add()中要生成一个新的list

                                                                         (2)dfs(i+1, n , k, path)中是i还是index

                                                                         (3)index产生12组,i产生6组

回溯剪枝:

         观察n=4,k=3的情况,以树形结构给出图:

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是0-1背包问题的回溯算法Java代码实现: ``` public class KnapsackBacktracking { private int maxWeight = 0; private boolean[] bestSolution; private int[] weights; private int[] values; private int capacity; public int knapsack(int[] weights, int[] values, int capacity) { this.weights = weights; this.values = values; this.capacity = capacity; bestSolution = new boolean[weights.length]; backtracking(0, 0, 0, new boolean[weights.length]); return maxWeight; } private void backtracking(int i, int weight, int value, boolean[] solution) { if (i == weights.length || weight == capacity) { if (value > maxWeight) { maxWeight = value; System.arraycopy(solution, 0, bestSolution, 0, solution.length); } return; } if (weight + weights[i] <= capacity) { solution[i] = true; backtracking(i + 1, weight + weights[i], value + values[i], solution); } solution[i] = false; backtracking(i + 1, weight, value, solution); } public boolean[] getBestSolution() { return bestSolution; } } ``` 其中,`knapsack()`方法接收物品重量数组`weights`、价值数组`values`和背包容量`capacity`,并返回最大价值。`backtracking()`方法是递归函数,用来搜索所有可能的解,并更新最优解。`maxWeight`和`bestSolution`分别用来保存最大价值和最优解。在递归过程中,如果当前重量或价值已经达到最大值,则结束递归。否则,对于每个物品,我们可以选择将其放入背包或不放入,分别递归求解。最后,通过`getBestSolution()`方法来获取最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值