每日一题
注意事项
- dfs 查找目标节点的时候,记得条件深度遍历,否则给 null 加 parent 属性就尴尬了
- 开始查找距离的时候,记得保存所有走过的节点,防止重复跑
- 使用 paths 保存走过的节点是因为向上查找过程中,你不晓得自己当前节点是属于父节点的左右哪个节点,做判断更麻烦,不如直接存储走过的节点,更好理解
// https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/
/**
*
* @param {TreeNode} root 根节点
* @param {TreeNode} target 目标节点
* @param {number} K 目标距离
*
* @分析
* 1. 题目已知具有根节点
* 2. 使用递归的方式求出目标节点,并且标记节点的父节点,辅助向上查找
*
*
*/
var distanceK = function (root, target, K) {
const res = []
const paths = [] // 存储在查找阶段查过的节点
let targetNode = null
const dfs = (root) => {
// 因为是判断递归,且根节点已知存在
// if (!root) return
if (root === target) {
targetNode = root
return
}
if (root.left) {
root.left.parent = root
dfs(root.left)
}
if (root.right) {
root.right.parent = root
dfs(root.right)
}
}
// 求出 targetNode,并为到达该节点前的节点设置 parent
dfs(root)
console.log(targetNode)
const findKNode = (root, k) => {
// 遍历结束或者已经查找过当前节点
if (!root || paths.indexOf(root) !== -1) return
paths.push(root)
if (k === 0) {
res.push(root.val)
} else {
k--
findKNode(root.left, k, paths)
findKNode(root.right, k, paths)
}
}
// 向下求节点
findKNode(targetNode, K)
// 向上求节点
while (targetNode.parent && K) {
// 每次往上走一次,就要减少
K--
targetNode = targetNode.parent
findKNode(targetNode,K)
}
return res
};
91算法
二分查找
// https://leetcode-cn.com/problems/sqrtx/
/**
* 向下取整求 x 的平方根
* @分析
* 1. 这里最后求向下取整的值,所以其实是求最左侧符合要求值
*/
var mySqrt = function (x) {
let left = 0
let right = x
while (left <= right) {
const mid = (left + right) >> 1 // 向下取整
const num = Math.pow(mid, 2)
if(num === x) return mid
if (num < x) {
// 取小了
left = mid + 1
} else {
// 取大了或者直接相等了,右边收缩
right = mid - 1
}
}
// 因为到了最后,是 right<left,退出循环,所以取小的值
return right
};
console.log(mySqrt(5))
console.log(mySqrt(6))
console.log(mySqrt(9))
第一个错误版本
// https://leetcode-cn.com/problems/first-bad-version/
// 最外层是为了提供一个检查版本错误的方法
var solution = function (isBadVersion) {
/**
* @分析
* 1. 求第一版的,那就是求最左的版本
* 2. 这道题默认是必然会有错误出现的
*
* @ 注意
* 1. 之前都是用 x >> 1 求 x/2 向下取整
* 2. 实际 >> 是带符号,为了取整,需要用 >>> 无符号右移,对于负数来说无所谓,对正数来说有区别
* 3. 当然也可以直接用 Math.floor
*/
return function (n) {
let left = 1
let right = n
while (left<=right){
// const mid = (left+right)>>1 // 向下取整
const mid = (left+right)>>>1 // 向下取整
// const mid = Math.floor((left+right)/2) // 向下取整
if(isBadVersion(mid)){
// 如果已经错误,则向左收缩
right = mid -1
}else{
// 如果这个还没有错误,则向右收缩
left = mid+1
}
}
// 需要判断是否越界了,这个时候
return left
};
};