每日一题 -- 树
1448. 统计二叉树中好节点的数目
// https://leetcode-cn.com/problems/count-good-nodes-in-binary-tree/
// 1448. 统计二叉树中好节点的数目
/**
* 前序遍历+扩展属性
* @分析
* 1. 在做极值判断的时候,必须看清是否是是正整数,初始判定值应该设置正反无穷;
* 2. 本题中初始的 max,一开始设置为 0,属于惯性坏习惯
*/
var goodNodes = function(root) {
if(!root) return 0
let count = 0
const dfs = (root,max) => {
if(!root) return
let val = root.val
if(max<=val){
console.log(val)
count++
}else{
val = max
}
dfs(root.left,val)
dfs(root.right,val)
}
dfs(root,-Infinity)
return count
};
91算法 -- 搜索
n 皇后2
分析
- row,col,dlr,dll分别是当前行,已经标记过的列标志,已经标记过的右斜标志,已经标记过的左斜标志
- 用 2 进制配合位运算来做一个做一个图
- 因为是递增的 row,所以行不需要判断
- 列直接就是取遍历过程中位移的 i
- dll表示从左往右的对角线,根据行和列之和来判断是否在对角线上,因为row 是递增的,所以这个对角线的点肯定在相应的右侧
- 同理 dlr 是从左到右的对角线,所以它的列是 n-i
- 每次 dfs 返回的是已经探查的并集 | , 然后判断是否跳过时用交集 &
- 如果交集都为 0,证明符合,只要有一个有交集,即不为0,则要跳过
// https://leetcode-cn.com/problems/n-queens-ii/
// n 皇后2
/**
* 位运算判断位置+dfs深度遍历
* @分析
* 1. row,col,dlr,dll分别是当前行,已经标记过的列标志,已经标记过的右斜标志,已经标记过的左斜标志
* 2. 用 2 进制配合位运算来做一个做一个图
* 3. 因为是递增的 row,所以行不需要判断
* 4. 列直接就是取遍历过程中位移的 i
* 5. dll表示从左往右的对角线,根据行和列之和来判断是否在对角线上,因为row 是递增的,所以这个对角线的点肯定在相应的右侧
* 6. 同理 dlr 是从左到右的对角线,所以它的列是 n-i
* 7. 每次 dfs 返回的是已经探查的并集 | , 然后判断是否跳过时用交集 &
* 8. 如果交集都为 0,证明符合,只要有一个有交集,即不为0,则要跳过
*
* 0100
* 0001
* 1000
* 0010
*/
var totalNQueens = function (n) {
if (n < 2) return n
let res = 0
const dfs = (row, col, dlr, dll) => {
// 走到尽头了,这条路是通的
if (row === n) return res++
for (let i = 0; i < n; i++) {
const _col = 1 << i,
_dlr = 1 << (n - i + row), //从左往右的对角线
_dll = 1 << (i + row) //从右往左的对角线
// 判断 _col,_dlr,_dll 是否已经存在于对应的二进制中,即判断是否符合要求,不符合就跳过当前这一条路
// 当 col & _col === 0 时,证明所在的位置和之前的列重合了
if ((col & _col) !== 0 || (dlr & _dlr) !== 0 || (dll & _dll) !== 0) continue;
// 符合要求,则继续走下一行,然后把对应的判断取交集
dfs(row + 1, col | _col, dlr | _dlr, dll | _dll)
}
}
dfs(0, 0, 0, 0)
return res
};
totalNQueens(4)