DFS+回溯法:皇后题(51LC困难)

搜索的过程蕴含了 剪枝 的思想。「剪枝」的依据是:题目中给出的 「N 皇后」 的摆放规则:1、不在同一行;2、不在同一列;3、不在同一主对角线方向上;4、不在同一副对角线方向上

小技巧:记住已经摆放的皇后的位置
这里记住已经摆放的位置不能像 Flood Fill 一样,简单地使用 visited 布尔数组。放置的规则是:一行一行考虑皇后可以放置在哪一个位置上,某一行在考虑某一列是否可以放置皇后的时候,需要根据前面已经放置的皇后的位置。

由于是一行一行考虑放置皇后,摆放的这些皇后肯定不在同一行,为了避免它们在同一列,需要一个长度为 NN 的布尔数组 cols,已经放置的皇后占据的列,就需要在对应的列的位置标注为 True。

为了保证至少两个皇后不同时出现在 同一主对角线方向 或者 同一副对角线方向。检查策略是,只要「检测」到新摆放的「皇后」与已经摆放好的「皇后」冲突,就尝试摆放同一行的下一个位置,到行尾还不能放置皇后,就退回到上一行。

可以像全排列 used 数组那样,再为 「主对角线(Main diagonal)」 和 「副对角线(Sub diagonal)」 设置相应的 布尔数组变量,只要排定一个 「皇后」 的位置,就需要占住对应的位置。

结合代码加注释:便于复习与分享...

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

class Solution{
private int n;
private boolean []col;//记录某一列是否放置皇后
private boolean[]main;//记录某一主对角线是否放置了皇后
private boolean[] sub;//记录副对角线是否放置了皇后
private List<List<String>>res;
  public List<List<String>>solveNQueens(int n){
res=new ArrayList<>();//设置为数组列表
if(n==0){
    return res;
}

//设置成员变量
this.n=n;
this.col=new boolean[n];
this.main=new boolean[2*n-1];
this.sub=new boolean[2*n-1];
Deque<Integer>path=new ArrayDeque<>();//队列,先进先出
dfs(0,path);//开始的行,和队列
return res;
    }

    private void dfs(int row,Deque<Integer>path){
        if(row==n){// 深度优先遍历到下标为 n,表示 [0.. n - 1] 已经填完,得到了一个结果
          List<String>board=convert2board(path);
          res.add(board);
          return;//满足上面的row==n,就return,递归结束的条件
        }
        for(int j=0;j<n;j++){// 针对下标为 row 的每一列,尝试是否可以放置
         if(!col[j]&&!main[row-j+n-1]&&!sub[row+j]){//每一列为false(未访问),主(副)对角线找到为false的位置
            path.addLast(j);
            col[j]=true;
            main[row-j+n-1]=true;
            sub[row+j]=true;

            dfs(row+1,path);//等价表达式,行数+1
            main[row-j+n-1]=false;//不满足的就回溯
            sub[row+j]=false;
             col[j]=false;
             path.removeLast();

         }
        }
    }
    private List<String>convert2board(Deque<Integer>path){//用来表示皇后数组的
        List<String>board=new ArrayList<>();
        for(Integer num:path){
           StringBuilder row = new StringBuilder();
            row.append(".".repeat(Math.max(0,n)));
            row.replace(num,num+1,"Q");
            board.add(row.toString());
        }
        return board;
    }
}


全部评论

相关推荐

不愿透露姓名的神秘牛友
05-29 22:21
Offer1:小马智行,深圳,测试开发工程师,17.0k*16.0,Offer2:追觅科技,深圳,嵌入式工程师,18.0k*15.0,
嵌软狗都不学:各位base深圳的同事,作为也是并肩作战的一员,今天想站在管理视角,和大家开诚布公地聊一聊:从近几个月的上下班数据对比看来,我们发现一个明显的差异:深圳同事的在岗时间普遍比苏州同事短。很多深圳同事早上9点之后才到公司,晚上不到 20 点就下班了;而总部那边,20点半甚至 22 点后还有不少同事在办公室忙碌,特别是研发团队,加班更是常态。相信去过苏州的同事,对这种场景都不陌生。我很好奇,这是因为苏州工作任务太重还是咱们深圳同事效率真的高到能在更短时间内完成工作?MOVA在深圳成立分公司是为了吸引更优秀的人才贡献更多更高质的价值,公司管理层给我反馈的是深圳招到的多是行业的专家大拿,大部分都是薪资比苏州高的,而且我们办公的租金等也远高于苏州的..MOVA虽脱胎于强壮的集团母体不久,各业务板块尚未实现全面盈利,虽说公司管理层目光长远,不纠结当下的人才投入,但行业内的普遍标准是,员工创造的价值要达到公司雇佣成本的 15 倍以上。大家不妨自我审视一下,自己是否达到了这个标准?如果是抱着划水、按时打卡走人拿毛爷爷的心态那不适合来MOVA,那样过下去不但自己过得尴尬也会影响MOVA这个大船的攻城略地的速度.我并非鼓励大家盲目加班,而是倡导高效工作,拒绝无效忙碌,不要让项目进度因低效受影响,也别把精力浪费在和苏州同事拼打卡时长上,提倡更高的人效比;考虑到两地地域和交通差异,相信大家会找最适合自己发挥的工作方式(比如按时下班后1小时到家晚饭后继续未竟工作等..)大家在遵守公司规章的情况下尽情地体现自己的能力价值,为MOV!和深圳公司争光我们在这边才能更安心更有信心的工作下去;请客BU长、名部门长、项目管理和各业务单元负责人,全面梳理团队情况,及时评估成员工作负荷与成果质量,坚决清退划水害虫痕疫,践行公司价值观,相互监督,防止管理漏洞及渎职。感谢人家的理解,也请人家多担待我的直言不讳……
点赞 评论 收藏
分享
05-23 20:31
已编辑
武汉大学 Java
内向的柠檬精在研究求职打法:注意把武大标粗标大 本地你俩不是乱杀
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务