初认回溯

回溯法解题套路

简单理解回溯就是暴力循环求解,但是此暴力求解并不是简单的for循环,而是对决策树循环遍历,回溯有一定的框架,根据学习内容,写下框架以及找的例子以便自己往后复习。算法套路文章皆以labuladong的书为主,结合自身理解,以java语言复现。

框架内容

遇到问题,首先思考这三个问题:
1.路径已经做出的选择;
2.选择列表:当前可以做出的选择;
3.结束条件,达到底层后,无法再做出选择的条件。
其框架可以写为:
	    List result = new ArrayList();
        void backTrace(路径,选择列表):
        if (满足条件) result 添加路径
        for( 路径:选择列表){
            判断条件
                    做出选择
            backTrace(路径,选择列表)
            撤回选择

两个实例

数组全排列问题

该题为LeetCode46题,整体思路与框架相似

class Solution {
	    List<List<Integer>> res;
	    public List<List<Integer>> permute(int[] nums) {
	        int len = nums.length;
	        res = new ArrayList<>();
        if (len == 0) {
            return res;
        }
        List<Integer> path = new ArrayList();
        backTrace(nums, path);
        return res;
    }
private void backTrace(int[] nums, List<Integer> path) {
    int n = nums.length;
    if (path.size()== n) {
        //添加的为List  需要新建ArrayList
        res.add(new ArrayList(path));
        return;
    }

    for (int i = 0;i<n;i++){
        // 判断条件:去除重复,若path中存在数字,则跳过
        if (path.contains(nums[i])) continue;
        //添加路径
        path.add(nums[i]);
        backTrace(nums,path);
        //删除路径
        path.remove(path.size()-1);
  	 	 }
    }
}
经典N皇后

N皇后为LeetCode51题,整体思路与框架相似
注意点 java的Arraylist 以及字符串无法确定对象元素内部位置以及替换,需要将其转为数组,然后再转为所需要的内容

class Solution {
    List<List<String>> res;
public List<List<String>> solveNQueens(int n ){
    res  = new ArrayList() ;
    char[][]   board = new char[n][n];
    for (int i = 0;i<n;i++)
        for(int j = 0;j<n;j++)board[i][j] = '.';
    traceBack(board,0);
    return res;
}


public void  traceBack(char[][] board,int row){
//终止条件 ,
    if (row == board.length){
        res.add(construct(board));
        return ;
    }

    for (int col =0 ;col<board.length;col++){
        //判断条件 看皇后位置
        if (!isValid( board, row,col)) continue;
        //添加路径
        board[row][col] ='Q';
        //进入下一步
        traceBack(board,row+1);
        //删除路径
        board[row][col] ='.';
    }
}

//这个方法就是实现 字符串内部位置替换
public List<String> construct(char[][]  board){
    List<String>  a = new ArrayList<>();
        for (int i = 0;i<board.length;i++){
            a.add(new String(board[i]));
        }
    return a;

}

//row表示第几行,col表示第几列
private boolean isValid(char[][] chess, int row, int col) {
    //判断当前列有没有皇后,因为他是一行一行往下走的,
    //我们只需要检查走过的行数即可,通俗一点就是判断当前
    //坐标位置的上面有没有皇后
    for (int i = 0; i < row; i++) {
        if (chess[i][col] == 'Q') {
            return false;
        }
    }
    //判断当前坐标的右上角有没有皇后
    for (int i = row - 1, j = col + 1; i >= 0 && j < chess.length; i--, j++) {
        if (chess[i][j] == 'Q') {
            return false;
        }
    }
    //判断当前坐标的左上角有没有皇后
    for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
        if (chess[i][j] == 'Q') {
            return false;
        }
    }
    return true;
 	}	
}
总结

遇到回溯, 默写框架,注意边界条件 灵活根据语言特性变换存储结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值