说明

回溯问题,实际上决策树遍历问题。只需思考3个问题:

  • 路径:已做的选择;
  • 选择列表:当前可以做的选择;
  • 结束条件:无法再做选择的条件。

框架

  1. result = []
  2. def backtrack(路径, 选择列表):
  3. if 满足结束条件:
  4. result.add(路径)
  5. return
  6. for 选择 in 选择列表:
  7. 做选择
  8. backtrack(路径, 选择列表)
  9. 撤销选择

全排列问题

获取全排列的所有路径。这里假设n个数都不相同,则共有n!条路径。

必读系列 4回溯算法解题套路框架 - 图1

  1. List<List<Integer>> res = new LinkedList<>();
  2. List<List<Integer>> permute(int[] nums) {
  3. LinkedList<Integer> track = new LinkedList<>();
  4. backtrace(nums, track);
  5. return res;
  6. }
  7. void backtrack(int[] nums, LinkedList<Integer> track) {
  8. // 结束 触发
  9. if(tack.size() == nums.length) {
  10. res.add(new LinkedList(track));
  11. return;
  12. }
  13. for(int i = 0; i < nums.length; i++) {
  14. // 排除不合法的选择
  15. if(track.contains(nums[i]))
  16. continue;
  17. // 做选择
  18. track.add(nums[i]);
  19. // 进入下一层决策树
  20. backtrack(nums, track);
  21. // 撤销选择
  22. track.reomveLast();
  23. }
  24. }

N 皇后问题

给你一个 N×N 的棋盘,让你放置 N 个皇后,使得它们不能互相攻击。皇后可以攻击同一行、同一列、左上左下右上右下四个方向的任意单位。

必读系列 4回溯算法解题套路框架 - 图2

  1. List<List<String>> res = new LinkedList<>();
  2. // 输入 棋盘 边长n , 返回所有的 合法 放置
  3. List<List<String>> solveNQueues(int n) {
  4. // '.' 表示空, 'Q'表示皇后 初始化空棋盘
  5. List<String> borad;
  6. backtrack(board, 0);
  7. return res
  8. }
  9. // 路径: board中 小于row的那些行已经成功放置了皇后
  10. // 选择列表: 第row行所以的列都是放置皇后的选择
  11. // 结束条件:row 超过 board 的最后一行
  12. void backtrack(List<String> board, int row) {
  13. // 已经超过最后一行,保存当前棋盘的状况
  14. if(row == board.size()) {
  15. res.add(board);
  16. return;
  17. }
  18. // 一行就是一个字符串 获取长度
  19. int len = board.get(row).length();
  20. for(int col = 0; col < len; col++) {