持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
LeetCode 75 —— 235. 二叉搜索树的最近公共祖先
一、题目描述:
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。 示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。 p、q 为不同节点且均存在于给定的二叉搜索树中。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/lo… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
我们找两个节点最近公共祖先可以从以下这个思路入手:
我们先求出从根节点到这两个节点的路径,然后再在路径中查找最近的公共祖先。
如何知道根节点到这两个节点的路径呢?
因为是二叉搜索树,所以我们从根节点出发,比较当前节点的Val值与目的节点的Val值,然后去寻找下一个节点。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是一次通过的,刚开始我的解法是这样的:
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { path1 := getPath(root,p) path2 := getPath(root,q) index := 0 for i:=0;i<len(path1) && i<len(path2) && path1[i] == path2[i];i++{ index = i } return path1[index] } func getPath(root, node *TreeNode) ( path []*TreeNode ) { path = append(path,root) for root != nil { if root.Val > node.Val{ root = root.Left path = append(path,root) }else{ root = root.Right path = append(path,root) } if root == node{ break } } return } 这样就会有一些问题,比如:
[2,null,3] 2 3到2的路径就会执行else语句块,然后往右边走。
最后路径就会变成: 2 3
到3的路径也会变成 2 3
这样就会导致lowestCommonAncestor执行的结果是3,而不是应当的2。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
func lowestCommonAncestor(root, p, q *TreeNode) (ancestor *TreeNode) {
ancestor = root
for {
if p.Val < ancestor.Val && q.Val < ancestor.Val {
ancestor = ancestor.Left
} else if p.Val > ancestor.Val && q.Val > ancestor.Val {
ancestor = ancestor.Right
} else {
return
}
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/solution/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-26/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、AC 代码:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
path1 := getPath(root,p)
path2 := getPath(root,q)
index := 0
// fmt.Println(path1,path2)
for i:=0;i<len(path1) && i<len(path2) && path1[i] == path2[i];i++{
// fmt.Println(path1[i].Val,path2[i].Val)
index = i
}
return path1[index]
}
func getPath(root, node *TreeNode) ( path []*TreeNode ) {
path = append(path,root)
for root != node {
if root.Val > node.Val{
root = root.Left
path = append(path,root)
}else{
root = root.Right
path = append(path,root)
}
}
return
}
四、总结:
我的两次遍历法时间复杂度和空间复杂度都为O(n),而一次遍历的时间复杂度是O(n),空间复杂度为O(1)。
模板来源:
作者:掘金酱
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。