Java 数据结构与算法之回溯法

一、概念

回溯法是一种优选搜索法,按照优先条件深度优先搜索,以达到目标。当搜索到某一步时,发现原先选择并不是最优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术成为回溯法,而满足回溯条件的某个状态成为“回溯点”

二、思想

回溯法是从初始状态出发,按照深度优先搜索的方式,根据产生子节点的条件约束,搜索问题的解。当发现当前节点不满足条件时,就回溯,尝试其他的路径。回溯法是一种“能进则进,进不了则换,换不了则退

回溯法的核心是递归,递归一定要会有个函数出口,否则会有死循环。

三、应用示例

1、N皇后

N-Queens

class Solution {
    public List> solveNQueens(int n) {
        List> res = new ArrayList<>();
        int[] queen = new int[n];
        helper(queen, 0, n, res);
        return res;
    }

    private void helper(int[] queen, int row, int n, List> res) {
        for (int i = 0; i < n; i++) {
            queen[row] = i;
            if (place(queen, row)) {
                if (row == n - 1) {
                    addToRes(queen, res);
                } else {
                    helper(queen, row + 1, n, res);
                }
            }
        }
    }

    private boolean place(int[] queen, int row) {
        for (int i = 0; i < row; i++) {
            if (queen[i] == queen[row] || Math.abs(queen[i] - queen[row]) == row - i) {
                return false;
            }
        }
        return true;
    }
    
    private void addToRes(int[] queen, List> res) {
        Listtmp=new ArrayList<>();
        for (int i = 0; i < queen.length; i++) {
            StringBuffer sb=new StringBuffer();
            for (int j=0;j

N-Queens ii

class Solution {
    
    private int count = 0;
    
    public int totalNQueens(int n) {
        int[] queen=new int[n];
        helper(queen,0,n);
        return count;
    }


    private void helper(int[] queen, int row, int n) {
        for (int i = 0; i < n; i++) {
            queen[row] = i;
            if (place(queen, row)) {
                if (row == n - 1) {
                    count++;
                } else {
                    helper(queen, row + 1, n);
                }
            }
        }
    }
        
    private boolean place(int[] queen, int row) {
        for (int i = 0; i < row; i++) {
            if (queen[i] == queen[row] || Math.abs(queen[i] - queen[row]) == row - i) {
                return false;
            }
        }
        return true;
    }
}

2、数独

Valid Sudoku

 

Sudoku Solver

class Solution {
    public void solveSudoku(char[][] board) {
        solveSudokuTmp(board);
    }

    public boolean solveSudokuTmp(char[][] board) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] == '.') {
                    for (char c = '1'; c <= '9'; c++) {
                        if (isValid(board, i, j, c)) {
                            board[i][j] = c;
                            if (solveSudokuTmp(board)) {
                                return true;
                            } else {
                                board[i][j] = '.';
                            }
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }

    private boolean isValid(char[][] board, int i, int j, char c) {
        for (int k = 0; k < 9; k++) {
            if (board[i][k] == c) {
                return false;
            }
            if (board[k][j] == c) {
                return false;
            }
            if (board[3 * (i / 3) + k / 3][3 * (j / 3) + k % 3] == c) {
                return false;
            }
        }
        return true;
    }
}

还有很多经典例子,不断更新中

你可能感兴趣的:(Java,数据结构与算法)