回溯算法

  • 回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。
  • 回溯法的基本行为是搜索,搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:1. 使用约束函数,剪去不满足约束条件的路径;2.使用限界函数,剪去不能得到最优解的路径。
  • 回溯算法说白了就是穷举法。不过回溯算法使用剪枝函数,剪去一些不可能到达 最终状态(即答案状态)的节点,从而减少状态空间树节点的生成,提高了效率。
  • 回溯算法一般都采用递归实现。回溯利用递归的性质,从问题的起始点出发,不断地进行尝试,回头一步甚至多步再做选择,直到最终抵达终点。

回溯解题模板

function backtrack(n, used) {// 判断输入或者状态是否非法if (input/state is invalid) {return;}// 判读递归是否应当结束,满足结束条件就返回结果if (match condition) {return some value;}// 遍历当前所有可能出现的情况,并尝试每一种情况for (all possible cases) {// 如果上一步尝试会影响下一步尝试,需要写入状态used.push(case)// 递归进行下一步尝试,搜索该子树result = backtrack(n + 1, used)// 在这种情况下已经尝试完毕,重置状态,以便于下面的回溯尝试used.pop(case)}
}

经典问题

leetcode17. 电话号码的字母组合
class Solution {private List<String> res = new ArrayList<>();private final String[] letterMap = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};public List<String> letterCombinations(String digits) {if (digits.length() == 0) {return res;}findCombination(digits, 0, "");return res;}private void findCombination(String digits, int index, String s){if(index == digits.length()){res.add(s);return;}Character c = digits.charAt(index);String letters = letterMap[c - '0'];for(int i = 0 ; i < letters.length() ; i ++){findCombination(digits, index+1, s + letters.charAt(i));}return;}
}
leetcode46. 全排列
public class Solution {private List<List<Integer>> res = new ArrayList<>();public List<List<Integer>> permute(int[] nums) {if (nums.length == 0) {return res;}boolean[] used = new boolean[nums.length];List<Integer> list = new ArrayList<>();backtrack(nums, 0, list, used);return res;}public void backtrack(int[] nums, int index, List<Integer> list, boolean[] used) {if (index == nums.length) {res.add(new ArrayList<>(list));return;}for (int i = 0; i < nums.length; i++) {if (!used[i]) {list.add(nums[i]);used[i] = true;backtrack(nums, index + 1, list, used);list.remove(list.size() - 1);used[i] = false;}}}
}
leetcode51. N皇后
class Solution {public List<List<String>> res = new ArrayList<>();public List<List<String>> solveNQueens(int n) {int[] cols = new int[n];for (int i=0; i<n; i++) {cols[i] = -1;}backtrack(0, n, cols);return res;}public void  backtrack(int index, int n, int[] cols) {if (index == n) {res.add(locToList(cols));return;}for (int i=0; i<n; i++) {cols[index] = i;if (isSafe(cols, index)) {backtrack(index+1, n, cols);}cols[index] = -1;}}public boolean isSafe(int[] cols, int index) {for (int i=0; i<index; i++) {if (cols[i] == cols[index] || i+cols[i] == index+cols[index] || i-cols[i] == index-cols[index]) {return false;}}return true;}public List<String> locToList(int[] cols) {ArrayList<String> list = new ArrayList<>();for (int i=0; i<cols.length; i++) {StringBuilder sb = new StringBuilder();for (int j=0; j<cols[i]; j++){sb.append(".");}sb.append("Q");for (int j=cols[i]+1; j<cols.length; j++){sb.append(".");}list.add(sb.toString());}return list;}
}

其他

递归与迭代
  • 计算机解决问题其实没有任何奇技淫巧,它唯一的解决办法就是穷举,穷举所有可能性。算法设计无非就是先思考“如何穷举”,然后再追求“如何聪明地穷举”。其中穷举的代码形式上有两种:递归和迭代
  • 重复调用函数自身实现循环称为递归。递归是用栈机制实现的,每深入一层,都要占去一块栈数据区域,所以有可能导致堆栈溢出的错误。思想简单,代码简洁,将问题交给计算机
  • 利用变量的原值推出新值称为迭代,或着说迭代是函数内某段代码实现循环。由于递归容易导致堆栈溢出,并且递归比迭代效率要低,所以尽量使用迭代
  • 递归是一个树结构,迭代是一个环结构
递归与递推
  • 递归是自顶向下(对应函数入栈),又自底向上(对应函数出栈)。可以在自顶向下的时候进行操作,也可以在自底向上的时候进行操作。
  • 递推是自底向上
两种实现形式
  • 状态记录回溯
  • 交换回溯

回溯算法总结(java)相关推荐

  1. 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现

    是使用递归方法实现回溯算法的,在第一次使用二维矩阵的情况下,又做了一次改一维的优化 但是算法效率仍然差强人意,因为使用递归函数的缘故 下面提供另一种回溯算法的实现,使用数据结构"栈" ...

  2. java实现回溯算法,java基础面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  3. 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同 ...

  4. 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案(一)

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同 ...

  5. 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化

    研究了递归方法实现回溯,解决N皇后问题,下面我们来探讨一下非递归方案 实验结果令人还是有些失望,原来非递归方案的性能并不比递归方案性能高 代码如下: package com.newflypig.eig ...

  6. [Leetcode][第81题][JAVA][N皇后问题][回溯算法]

    [问题描述][困难] [解答思路] 1. 主副对角线列 标记 复杂度 import java.util.ArrayDeque; import java.util.ArrayList; import j ...

  7. [Leedcode][JAVA][第46题][全排列][回溯算法]

    [问题描述] 46.全排列 (中等) 给定一个 没有重复 数字的序列,返回其所有可能的全排列.示例:输入: [1,2,3] 输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[ ...

  8. java 回溯_java 实现迷宫回溯算法示例详解

    用一个7 x 7的矩形表示迷宫,0和1分别表示的是通路和障碍.通过设计编写程序找到蓝色小球达到蓝色旗子的路线 思路: 构建一个迷宫(用二维数组)实现找通路的方法findRoad() 构建二维数组不难, ...

  9. java符号三角形问题_实验四 回溯算法和分支限界法 符号三角形问题

    基本题一:符号三角形问题 一.实验目的与要求 1.掌握符号三角形问题的算法: 2.初步掌握回溯算法: 二.实验题图 下面都是"-".下图是由14个"+"和14个 ...

  10. java回溯算法_回溯算法讲解--适用于leetcode绝大多数回溯题目

    什么是回溯算法? 回溯法是一种系统搜索问题解空间的方法.为了实现回溯,需要给问题定义一个解空间. 说到底它是一种搜索算法.只是这里的搜索是在一个叫做解空间的地方搜索. 而往往所谓的dfs,bfs都是在 ...

最新文章

  1. Base64的编码规则和C#实现
  2. 开源点评:Protocol Buffers介绍
  3. vlan间路由的问题
  4. LeetCode(892)——三维形体的表面积(JavaScript)
  5. 为什么我在实时编码时失败了?
  6. MAC安装软件 brew 问题记录
  7. git提交错分支怎么办
  8. 项目上传图片报:Can't create output stream!
  9. go实现 LeetCode 1227 飞机座位分配概率
  10. git fatal: cannot lock ref ‘HEAD‘:unable to resolve reference‘refs/heads/main‘:reference broken
  11. TCP的拥塞避免、超时重传、快速重传、快速恢复
  12. Linux学习整理-网络防火墙firewalld
  13. mysql中单个表脏读_如何在Outlook中单击邮件后立即将其标记为已读
  14. 和《盗梦空间》无关。
  15. 计算机网络(期末详细总结)
  16. 深度 | 车载语音群雄并起共争智能座舱新高地
  17. 游戏音乐外包中的重要人物--商务
  18. SAP中使用MM01创建物料如何选定行业领域和物料类型
  19. MFC:error MSB8008: 指定的平台工具集(v141)未安装或无效。请确保选择受支持的 PlatformToolset 值
  20. 最简单的解释-Java父类和子类的初始化顺序

热门文章

  1. 微信开发一服务器地址(URL)、令牌(Token)配置
  2. 论如何优雅的用Vue从前台导入excel(并处理单元格合并问题)
  3. 使用selenium抓取1688供应商
  4. spring boot配置Jackson详解
  5. wifi 3A认证总体架构设计思路
  6. php 截取视频画面,什么软件可截取视频画面,电脑上方便的截取视频,截取视频该怎么操作...
  7. 创建deployment
  8. PDM数据表结构字段导出到excel
  9. 干货 | CrateDb在携程机票BI的实践
  10. 基于uml的大学图书馆图书信息管理系统设计实验_气味图书馆 | 这些学校的#后悔没读#和#还想再读#系列...