一:二叉搜索树与双向链表
题目:
分析:
在不考虑空间复杂度的要求下,我们可能会使用链表这一容器进行操作。再结合一个中序遍历即为
最终的结果。
但是题目要求是在原树的基础上进行修改指针的指向,进而实现二叉搜索树到双向链表的操作。
首先肯定是借助中序遍历的思想进行改变指针的指向
中序遍历:输出的是一个升序的序列
借助2个指针形成一前一后的关系,进而改变指针的链接。
草图:
细节的处理:
1)题目要求最后返回双向链表的头结点,所以这里就不能直接返回当期指向成cur ,因为此时节点
指向已经发生了更替。所以需要在进行对二叉树修改之前先找到最小的节点
2)这里借助子函数 _Convert(TreeNode* cur,TreeNode*pre) 实现内部指针的修改。
OJ代码:
cpp
#include <cstddef>
#include <limits>
class Solution {
public:
void _Convert(TreeNode*cur,TreeNode*&pre )
{
if(cur == nullptr)
return;
//进行一个中序的遍历
_Convert(cur->left,pre);
// 改变左右指针链接
//pre的right 指向后继
//cur 的left 指向前驱
if(pre)
pre->right = cur;
cur->left = pre;
//进行迭代
pre = cur;
_Convert(cur->right,pre);
}
TreeNode* Convert(TreeNode* _root)
{
TreeNode* head = _root;//头结点:
if(head == nullptr)
return nullptr;
//找最小节点
while(head && head->left)
{
head = head->left;
}
TreeNode* cur = _root,*pre = nullptr;//形成一前一后,左右指针改变
_Convert(cur,pre);
return head;
}
};
二:二叉树的最近公共祖先
题目:
分析:
从大方向来说,节点 p,q ,不是位于根节点的同侧就是位于两侧。
对于一个树而言不是根节点就是孩子节点。
这里采用假设的思想:先假设节点p 在左边:pInLeft
pInRight:表示节点p 位于右边
同理:qInLeft ,假设q位于左边
OJ代码:
cpp
bool IsInTree(TreeNode* root,TreeNode* node)
{
if(root == nullptr)
return false;
if(root == node)
return true;
return IsInTree(root->left,node) || IsInTree(root->right,node);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
// bool pInLeft = IsInTree(root,p);
//假设p 是左孩子
bool pInLeft = IsInTree(root->left,p);
bool pInRight = !pInLeft;
// bool qInLeft = IsInTree(root,q);
//假设p 是左孩子
bool qInLeft = IsInTree(root->left,q);
bool qInRight = !qInLeft;
//是否满足一上一下的情况
if(root == p || root == q)
return root;
//位于最近祖先的两侧
if(pInLeft && qInRight || pInRight && qInLeft)
return root;
//位于同侧
if(pInLeft && qInLeft)
return lowestCommonAncestor(root->left,p,q);
if(pInRight && qInRight)
return lowestCommonAncestor(root->right,p,q);
return nullptr;
}
对于二叉搜索树在OJ 里面的应用还是有一定的难度的,不仅要求我们对二叉搜索树的性质以及结
构熟练掌握,还需要结合草图进行理解,对于二叉搜索树的理论讲解有需要的可以康康此篇博客。
二叉搜索树,希望各位可以有所收获。