如果面试碰到这么难的题..感觉可以挂电话了。
这题看到首先第一个可以确定的是这个肯定会用到DFS backtracking. 怎么知道的? 因为一看就发现能够尝试的组合实在是太多了,运算量非常大。如果我们用iterative 迭代来做,会做到吐血。一般这种情况就用backtrack来做,设置一些condition.
知道了这些似乎也没什么卵用。
首先明确一下什么情况为solution。在整个棋盘上,没有任何两个骑士棋子,在同一行或者同一列或者对角线。知道了规则,因为我们要返回的是arrays, 所以怎么说我们也得先声明好array。
初始化array也很容易出错,我们要往上面摆满 "." 还不是全是空的。 initialize的方式可以是
char[][] curr = new char[n][n]; //2D array,这里要注意。
for (char[] row : curr) {
//fill out fill '.';
Arrays.fill(row, '.');
}
接下来,从第一行开始,我们可以一个一个的试着放棋子。 假设骑士棋子在第一行第一个,接下去的棋子怎么放才可以。然后碰到很明显不行的,直接放弃那个尝试。【这个就是backtracking】。
其实整个structure跟combination sum阿,以及好多的DFS, backtracking非常像。
大概结构
main function:
调用DFS func
DFS func:
if condition: return;
for loop:
IF: 做一个判断看看能不能加新东西:
增加一些东西
把增加的东西拿到DFS 里递归recursion.
还原,把这一次加入的给删掉。
整体看下来, 最难的部分是如何设置判断的情况。毕竟每一次的判断valid 与否都要跟本行上面所有行的棋子做比较。 而且还带对角线比较。
对角线判断:当前放置的东西的行数与前一行放置的东西的行数的差的绝对值跟他们的列的差的绝对值一样就在对角线。
跟previous rows比较的时候,每一行我们比较3个地方。 一样的col位置,以及左右两边的col位置。
跟previous row比较的时候,每一行我们比较3个地方,一样的col位置,以及之前的row的左右两个col是否会和当前棋子在同一个对角线上
只要有一行不符合,就return false。
判断这个点往上的斜对角线。
# 今天看视频,发现一个更牛逼的解法。。。之前的解法是我们没到一个位置都要回溯之前的diagnol判断。但是完全可以设立红色对角线和蓝色对角线。并且对角线ID 根据x,y决定!