回溯法经典题目训练,一文读懂拿下

回溯法

废话不多说:回溯模板

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }
    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

回溯是递归的副产品,只要有递归就会有回溯,所以回溯法也经常和二叉树遍历,深度优先搜索混在一起,因为这两种方式都是用了递归。回溯法就是暴力搜索,并不是什么高效的算法,最多再剪枝一下。

  • 我们把回溯抽象树形结构看:横向遍历,加纵向遍历:
    在这里插入图片描述

能够解决的问题:

组合问题: N个数里面按一定规则找出k个数的集合

77.组合
216.组合总和III
17.电话号码的字母组合
39.组合总和
40.组合总和II

分割问题: 一个字符串按一定规则有几种切割方式

131.分割回文串
93.复原IP地址

子集问题 一个N个数的集合里有多少符合条件的子集

78.子集
90.子集II

排列问题: N个数按一定规则全排列,有几种排列方式

46.全排列
47.全排列II

棋盘问题

51.N皇后
37.解数独

其他

491.递增子序列
332.重新安排行程

实例:51 N皇后

n个皇后在棋盘NxN中,互不攻击(直线,横线,斜线只有一个皇后),求多少中摆放

class Solution {
    int sum=0;
    public int totalNQueens(int n) {
        char[][] box=new char[n][n];
        backtrack(n,0,box);
        return sum;
    }
    //回溯模板
    public void  backtrack(int n,int row, char[][] box){
        //终止条件,遍历到最后一行
        if(row==n){
            sum++;
            return;
        }
        for(int col=0;col<n;col++){
            if(isValid(row,col,n,box)){
                box[row][col]=1;
                backtrack(n,row+1,box);
                box[row][col]=0;
            }
        }
    }
    //验证是否直线,竖线,斜线上出现过
    public boolean isValid(int row,int col,int n,char[][] box){
         for(int i=0;i<row;i++){
             if(box[i][col]==1) return false;
         }
         for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--){
             if(box[i][j]==1) return false;
         }
         for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++){
             if(box[i][j]==1)return false;
         }
         return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值