题意
给定一棵二叉搜索树,请找出其中第 k
大的节点的值。
解法1—右根左递归遍历
一颗二叉搜索树,它的左子树上的所有节点比根节点小,它的右子树上的所有节点都比根节点大。并且左右子树也满足上述性质。
因此,如果是对二叉搜索树进行中序遍历(左根右),得到的结果就是 递增序列。根据以上性质,易得二叉搜索树的 中序遍历倒序(右根左) 为 递减序列 。因此,求 “二叉搜索树第 k 大的节点” 可转化为求 “此树的中序遍历倒序的第 k 个节点”。
C++实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution
{
private:
int k,res=0;
public:
int kthLargest(TreeNode* root, int k)
{
/*
// 右根左遍历顺序。当前如果遇到了第k个节点,就直接返回第k个节点的值
stack<TreeNode*> st; //存放节点的栈
TreeNode* cur=root;
while(!st.empty()||cur)
{
while(cur) //沿着cur的右孩子方向,将在这条路上的节点统统加入栈中,直到遇到最右边的节点
{
st.push(cur);
cur=cur->right;
}
cur=st.top();
st.pop();
k--;
if(0==k)
return cur->val;
cur=cur->left; //将最右边的节点的左孩子这一脉加入栈中
}
return -1;
*/
this->k=k;
dfs(root);
return res;
}
void dfs(TreeNode* root)
{
//递归出口,如果root为空或者找到了第k大节点就直接返回,结束本函数
if(NULL==root||0==k)
return;
dfs(root->right); //右。一直往右遍历
if(--k==0) //根。
{
//判断当前节点是不是第k大节点,如果是,
//将本节点的值返回给res,并且结束本函数,避免后序的无效dfs(root->left)
res=root->val;
return;
}
dfs(root->left); //左。
}
};
解法2—左根右非递归遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution
{
public:
int kthLargest(TreeNode* root, int k)
{
// 右根左遍历顺序。当前如果遇到了第k个节点,就直接返回第k个节点的值
stack<TreeNode*> st; //存放节点的栈
TreeNode* cur=root;
while(!st.empty()||cur)
{
while(cur) //沿着cur的右孩子方向,将在这条路上的节点统统加入栈中,直到遇到最右边的节点
{
st.push(cur);
cur=cur->right;
}
cur=st.top();
st.pop();
k--;
if(0==k)
return cur->val;
cur=cur->left; //将最右边的节点的左孩子这一脉加入栈中
}
return -1;
}
};
中序遍历倒叙(右根左)遍历模块
//打印中序遍历
void dfs(TreeNode* root )
{
if(!root) return;
dfs(root->left); //左
print(root->val); //根
dfs(root->right); //右
}
思考:这是是第K大,所以右根左遍历顺序(得到的是递减顺序);如果是求第K小就用左根右遍历顺序(得到的是递增顺序)。