zoukankan      html  css  js  c++  java
  • 五大常用算法--回溯

    概念

    回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

    关键词汇

    解空间树、决策树、DFS

    伪代码

    result = []
    def backtrack(路径, 选择列表):
          if 满足结束条件
              result.add(路径)
              return
    
           for选择 in 选择列表
               做选择   // 相当于二叉树的前序遍历
               backtrack(路径, 选择列表)
               撤销选择 // 相当于二叉树的后序遍历
    树遍历
    void traverse(TreeNode root) {
        for (TreeNode child : root.childern)
            // 前序遍历需要的操作
            traverse(child);
            // 后序遍历需要的操作
    }

    经典例子

    全排列

    package backtracing;
    
    import java.util.ArrayList;
    import java.util.List;
    // 求n的全排列
    public class PermutePrac {
        private List<List<Integer>> listList = new ArrayList<>();
    
        public List<List<Integer>> permute(int[] nums) {
            int len = nums.length;
            backTrack(new ArrayList<>(), len, nums);
            return listList;
        }
    
        public void backTrack(List<Integer> list, int n, int[] nums) {
            // 判断回溯值
            if (list.size() == n) {
                listList.add(new ArrayList<>(list));
            }
            // 遍历
            for (int i = 0; i < n; i++) {
                // 约束条件
                if (list.contains(nums[i])) {
                    continue;
                }
                list.add(nums[i]);
                backTrack(list, n, nums);
                // 回溯
                list.remove(list.size() - 1);
            }
        }
    }

    八皇后

    package backtracing.nqueen;
    
    import java.util.ArrayList;
    import java.util.List;
    
    // leetcode 51
    //
    // 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
    //
    // 每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
    // 
    // 示例:
    //
    // 输入: 4
    // 输出: [
    // [".Q..",  // 解法 1
    // "...Q",
    // "Q...",
    // "..Q."],
    //
    // ["..Q.",  // 解法 2
    // "Q...",
    // "...Q",
    // ".Q.."]
    // ]
    
    public class Solution {
        List<List<String>> listlist = new ArrayList<>();
    
        public List<List<String>> solveNQueens(int n) {
            solveNQueenUtil(0, n, new ArrayList<>());
            return listlist;
        }
    
        private void solveNQueenUtil(int row, int n, List<String> list) {
            if (row == n) {
                listlist.add(new ArrayList<>(list));
                return;
            }
    
            for (int col = 0; col < n; col++) {
                list.add(generateColn(col, n));
                if (isSafe(list, n)) {
                    solveNQueenUtil(row + 1, n, list);
                }
                list.remove(list.size() - 1);
            }
        }
    
        private String generateColn(int col, int n) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < n; i++) {
                if (i == col) {
                    sb.append("Q");
                } else {
                    sb.append(".");
                }
            }
            return sb.toString();
        }
    
        boolean isSafe(List<String> list, int n) {
            return isColSafe(list, n) && isLeftDiagnoseSafe(list, n) && isRightDiagnoseSafe(list, n);
        }
    
        boolean isColSafe(List<String> list, int n) {
            for (int col = 0; col < n; col++) {
                int count =  0;
                for (int row = 0; row < list.size(); row++) {
                    if (list.get(row).charAt(col) == 'Q') {
                        count++;
                    }
                }
                if (count > 1) {
                    return false;
                }
            }
            return true;
        }
    
        boolean isLeftDiagnoseSafe(List<String> list, int n) {
            for (int col = 0; col < n; col++) {
                int nextRow = 0;
                int nextCol = col;
                int count = 0;
                if (leftDianoseUtil(list, nextRow, nextCol, count)) return false;
            }
    
            for (int row = 0; row < list.size(); row++) {
                int nextRow = row;
                int nextCol = n - 1;
                int count = 0;
                if (leftDianoseUtil(list, nextRow, nextCol, count)) return false;
            }
            return true;
        }
    
        private boolean leftDianoseUtil(List<String> list, int nextRow, int nextCol, int count) {
            while (nextRow < list.size() && nextCol >= 0) {
                if (list.get(nextRow).charAt(nextCol) == 'Q') {
                    count++;
                }
                nextCol--;
                nextRow++;
            }
            if (count > 1) {
                return true;
            }
            return false;
        }
    
        boolean isRightDiagnoseSafe(List<String> list, int n) {
            for (int col = n - 1; col >= 0; col--) {
                int nextRow = 0;
                int nextCol = col;
                int count = 0;
                if (rightDianoseUtil(list, n, nextRow, nextCol, count)) return false;
            }
    
            for (int row = 0; row < list.size(); row++) {
                int nextRow = row;
                int nextCol = 0;
                int count = 0;
                if (rightDianoseUtil(list, n, nextRow, nextCol, count)) return false;
            }
            return true;
        }
    
        private boolean rightDianoseUtil(List<String> list, int n, int nextRow, int nextCol, int count) {
            while (nextRow < list.size() && nextCol < n) {
                if (list.get(nextRow).charAt(nextCol) == 'Q') {
                    count++;
                }
                nextCol++;
                nextRow++;
            }
            if (count > 1) {
                return true;
            }
            return false;
        }
    
        public static void main(String[] args) {
            Solution solution = new Solution();
            solution.solveNQueens(4);
            System.out.println(solution.listlist);
        }
    }

    参考资料:

    1. https://leetcode-cn.com/problems/n-queens/solution/hui-su-suan-fa-xiang-jie-by-labuladong/ (主要参考)

    2. https://leetcode-cn.com/problems/n-queens/solution/nhuang-hou-by-leetcode/

  • 相关阅读:
    UML序列图总结
    数据库水平切分的实现原理解析
    oracle imp file data
    putty的设置
    run java jar command
    forex website
    forex tables
    ubuntu set defult jdk
    友情连接
    jstl tag
  • 原文地址:https://www.cnblogs.com/harry1989/p/12082011.html
Copyright © 2011-2022 走看看