回溯算法模板写法以及样例

1、回溯算法

  • 1.1 概念:搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
  • 1.2 要点:在回溯点的时候,做了什么需要还原
  • 1.3 一般步骤:
    针对给出的问题,确定问题的解空间(简单来说就是暴力法找到所有解)
    确定结点的扩展搜索规则
    以深度优先的方式搜索解空间,并在搜索过程中,使用剪枝的思想减少算法复杂度

例题1:leetcode 46 全排列

/*
给定一个 没有重复 数字的序列,返回其所有可能的全排列
示例:
输入:[1,2,3]
输出:
[
	[1,2,3]
	[1,3,2]
	[2,1,3]
	[2,3,1]
	[3,1,2]
	[3,2,1]
]
*/
// 思路:
// 步骤1:暴力做法也很容易想到,枚举所有可能的结果(这就是我们的解空间)
// 步骤2:节点扩展规则:解释一下,就是相邻两个解不同,从那一步开始导致了这样的变化。
// 步骤3:...
public List<List<Integer>> permute(int[] nums) {
   
	int len = nums.length;
    List<List<Integer>> res = new ArrayList();
    if(len == 0){
   
        return res;
    }
    boolean[] used = new boolean[len];
    Deque<Integer> path = new LinkedList();
    dfs(nums, len, 0, used, path, res);
    return res;
}
private void dfs(int[] nums,int len, int depth, boolean[] used,Deque<Integer> path, 					List<List<Integer>> res){
   
    // 递归出口
    if(depth == len){
   
        res.add(new ArrayList(path));
        return;
    }
    for(int i = 0; i < len; i++){
   
        if(used[i]){
   
            continue;
        }
        // 下面这两步,对我们函数造成了影响
        // 在回溯完之后,我们需要把这些影响消除
        path.addLast(nums[i]);
        used[i] = true;
        dfs(nums,len,depth+1,path,res);
        path.removeLast();
        used[i] = false;
    }
}

例题2:leetcode 47 全排列Ⅱ

/*
给定一个可包含重复数字的序列,返回所有不重复的全排列。

输入: [1,1,2]
输出:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]
*/

// 这一题与上一题不同在于包含重复数,重复数就会造成重复结果,
// 我们按照前议题的思路来看一下重复结果是怎么出来的
// 第一次我们选第一个1,然后选第二个1,再选2。 得到第一组解
// 然后是选第一个1,选2,再选第二个1,得到第二组
// 选第二个1,选第一个1,选2。得到第三组解


// 我们现在是得到完整的结果集合了,但是需要排除一些多余的解
// 现在需要思考怎么把这组解排除。(朴素的思想是用set,但ac不了)
// 这我们就需要剪枝,把不需要运算的结果,从我们的结果集中去掉

class Solution {
   
    public List<List<Integer>> permuteUnique(int[] nums) {
   
        int len = nums.length;
        Arrays.sort(nums);	// 排序之后,保证相等数是前后相邻的
        List<List<Integer>> res = new ArrayList<>();
        if(len == 0
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值