每日一题 -- 树
感想
- 做的过程中首先想到的是先遍历找到目标节点 P,然后再走一步就好了
- 但是下一步怎么走,如果是左节点,就应该走它的父节点;如果是父节点,就应该走右子节点;如果是右子节点,那么就是左子节点;三种情况;
- 但是这样做就的在做 dfs 过程中维护当前遍历的子树的状态,感觉有点麻烦,就想下一种方法,
- 然后就想着还是按照一般中序遍历将所有节点都罗列出来,在中序 push 节点的时候,判断一下是否是 target 节点,保存一下当前的 index,就可以在遍历完整颗树之后找到这个节点了。
- 后面想了一下,其实不用维护整个数组,直接维护一个 finished 状态即可
// https://leetcode-cn.com/problems/successor-lcci/
/**
* @分析
* 1. 中序遍历,插入所有遍历到的节点
* 2. 判断是否是 target 节点,然后记录当前的 pos
* 3. 从遍历的数组中取 pos 的下一个节点
* 4. 如果超出了数组,则证明没有下一个节点,返回 null
*
* @时间复杂度
* 正常的中序遍历 $O(logn)$
*
* @空间复杂度
* 使用了数组保存树节点 $O(n)$
*/
var inorderSuccessor = function(root, p) {
const res = []
let pos = 0
let index = 0
const dfs = (root) => {
if(!root) return
dfs(root.left)
res.push(root)
if(root === p){
pos = index
}
index++
dfs(root.right)
}
dfs(root)
return res[pos+1] || null
};
var inorderSuccessor2 = function(root, p) {
let isFinished = false
let res = null
const dfs = (root) => {
if(!root) return
dfs(root.left)
if(isFinished){
res = root
// 在递归中 return 出去只是当前这个函数,还不能直接跳到根函数,所以要把状态关掉
isFinished = false
return
}
if(root === p){
// 已经找到了,然后就返回下一个即可
isFinished = true
}
dfs(root.right)
}
dfs(root)
return res
};
91算法
二分查找
// https://leetcode-cn.com/problems/find-peak-element/
/**
* @分析
* 1. 峰值元素大于左右相邻值的元素
* 2. 设置两个安全守卫为负无穷,保证能够获取到对应的值
* 3. 使用全局变量 res 可以根据这个值是否获取来终止其他的递归函数
*/
var findPeakElement = function (nums) {
let res = undefined
nums[-1] = nums[nums.length] = -Infinity
const recursion = (left, right) => {
if (res || left > right) return
const mid = left+Math.floor((right-left)/2)
if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) {
res = mid
return
}
if (nums[mid] < nums[mid - 1] && nums[mid] < nums[mid + 1]) {
// 处于谷值
recursion(left, mid - 1)
recursion(mid + 1, right)
} else if (nums[mid] > nums[mid - 1]) {
// 三个点递增,则收缩左侧
recursion(mid + 1, right)
} else {
// 三个点递减,则收缩右侧
recursion(left, mid - 1)
}
}
recursion(0, nums.length - 1)
if(res){
return nums[res]>nums[nums.length-1]?res:nums.length-1
}
return res
};
说明
本来应该昨天晚上发,但是昨天晚上锻炼的时候,电脑一直开着直到没电关机了;emm,一般下班回家的时候我都是直接带满电的电脑回家的,它么电我也很纳闷,没法再掘金发咯。所以只能用我的手机充电器充满了,早上发一个,这个其实是昨天早上写的。
91也会在这个月结束了,基本早上时间都是算法,顺序是每日一题(自己的专题刷,现在是树),然后是91,如果还有时间就是刷 LC 的每日一题;争取 2021 结束能拿个鼠标垫;加油鸭,干饭人。