hash数组与二进制 + 递归模拟回溯
前言
数据结构 与 经典思想的组合是算法常考的方式之一。还有另一种类型,脑筋急转弯型,需要我们去发现问题内涵与规律。
N皇后 II 包含了算法常考的两种方式,元素丰富。有常见的hash数组赋能;二进制对hash数组状态压缩;递归回溯模拟;矩阵左右斜线处理方式(算是嵌套了脑筋急转弯元素在里面)。
一、N皇后 II
二、hash数组赋能 + 递归回溯模拟
1、hash+DFS
//N 皇后 II
public class TotalNQueens {
/*
Pre-hash数组 + 模拟即可。
*/
public int totalNQueens(int n) {
/*int[] col = new int[n];
int[] left = new int[2 * n - 1];
int[] right = new int[2 * n - 1];*/
return dfs(new int[n], new int[2 * n - 1], new int[2 * n - 1], n, 0);
}
private int dfs(int[] col, int[] left, int[] right, int n, int level) {
if (n == level) return 1;
int rs = 0;
for (int i = 0; i < n; i++) {
if (col[i] == 0 && right[i - level + n - 1] == 0 && left[level + i] == 0) {
col[i] = right[i - level + n - 1] = left[level + i] = 1;
rs += dfs(col, left, right, n, level + 1);
col[i] = right[i - level + n - 1] = left[level + i] = 0;
}
}
return rs;
}
}
2、二进制状态压缩
//短hash数组(0-15)常见的状态压缩优化方式。
//用16位二进制表示,一个数代表整个hash数组。
class TotalNQueens2 {
/*
二进制对短hash数组压缩 + 模拟即可。
*/
public int totalNQueens(int n) {
return dfs(0, 0, 0, n, 0);
}
private int dfs(int col, int left, int right, int n, int level) {
if (n == level) return 1;
int rs = 0;
for (int i = 0; i < n; i++) {
if ((col & 1 << i) == 0 && (right & 1 << i - level + n - 1) == 0 && (left & 1 << level + i) == 0) {
col |= 1 << i;
right |= 1 << i - level + n - 1;
left |= 1 << level + i;
rs += dfs(col, left, right, n, level + 1);
col -= 1 << i;
right -= 1 << i - level + n - 1;
left -= 1 << level + i;
}
}
return rs;
}
}
总结
1)常见hash数组赋能操作。
2)常见短hash数组二进制状态压缩。
3)常见递归回溯模拟。
参考文献
[1] LeetCode N 皇后 II