每日一题算法:2020年9月3日 [N 皇后] solveNQueens

tech2022-11-04  117

2020年9月3日 N 皇后 solveNQueens

class Solution { public List<List<String>> solveNQueens(int n) { } }

解题思路:

思路1,暴力递归。

我们遍历棋盘的每一种组合形式,从而暴力得出所有可能的情况。

首先第一列,同一列中不会出现两个Q,所以,我们第一列存在n中情况,我们在每一种情况中都将所有不能再放Q的位置上使用“.”来填充,没被限制的还是使用默认的0x00来填充。

第二列由于不能和第一列的Q处于同一行以及同一斜线,就在第二列允许填充的位置上填充就可以了。

以此类推,知道棋盘最后一列放下Q或者无法放下Q为止。

在实现代码的过程中发现需要使用回溯。而且回溯的是一个二维数组,看来又得复习一下回溯算法了。在回溯的过程中一定要非常注意值传递和指针传递的问题。

在去查找回溯算法教程的时候就看到了很多的八皇后的题目,这让我更加确信自己的方向是没有错的。

肯定还存在调优的方式。

class Solution { char[][] map; int n; List<List<String>> res=new ArrayList<>(); public List<List<String>> solveNQueens(int n) { this.n=n; //遍历n次,放在第一列的第n个上,然后开始第二个 for (int index=0;index<n;index++){ map=new char[n][n]; map[0][index]='Q'; addQ(0,index,map); bulidMap(1,map); } return res; } //输入第几列,它会在这一列中找出一个能下Q的位置放下Q public void bulidMap(int index,char[][] mapT){ //如果到达了末尾,构建字符串 if (index==n){ res.add(mapToString(mapT)); return; } //复制map,准备回溯 char[][] newmap=new char[n][n]; for(int i=0;i<n;i++){ System.arraycopy(mapT[i],0 ,newmap[i],0 ,n); } //找一个可以放下的位置放下Q for (int i=0;i<n;i++){ if (mapT[index][i]==0){ mapT[index][i]='Q'; addQ(index,i,mapT); bulidMap(index+1,mapT); //递归后回溯,变回原本的二维数组 for(int j=0;j<n;j++){ System.arraycopy(newmap[j],0 ,mapT[j] ,0 ,n); } } } } //给出坐标,将统一横竖斜线上的所有其他位置给覆盖成 '.' public void addQ(int x,int y,char[][] mapT){ for (int i=0;i<n;i++){ if (mapT[x][i]==0){ mapT[x][i]='.'; } } for (int i=0;i<n;i++){ if (mapT[i][y]==0){ mapT[i][y]='.'; } } for (int i=0;i<n;i++){ if (x+i<n&&y+i<n){ if (mapT[x+i][y+i]==0) mapT[x+i][y+i]='.'; } if (x+i<n&&y-i>=0){ if (mapT[x+i][y-i]==0) mapT[x+i][y-i]='.'; } if (x-i>=0&&y+i<n){ if (mapT[x-i][y+i]==0) mapT[x-i][y+i]='.'; } if (x-i>=0&&y-i>=0){ if (mapT[x-i][y-i]==0) mapT[x-i][y-i]='.'; } } } public List<String> mapToString(char[][] mapT){ List<String> res=new ArrayList<>(); for (int i=0;i<n;i++){ res.add(new String(mapT[i])); } return res; } }
最新回复(0)