题解 | #二叉搜索树的第k个结点#
二叉搜索树的第k个结点
http://www.nowcoder.com/practice/ef068f602dde4d28aab2b210e859150a
思路
既然题中的树是二叉搜索树,所以中序遍历顺序即为从小到大的访问顺序。这一点要直接反应过来!!!
知道是中序遍历后就采用递归或非递归两种方法都可以了
方法一:递归中序遍历
递归中序的函数结构为
- 递归左子树
- 访问当前结点
- 递归右子树
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* res; // 采用一个全局的res指针来指向最终返回结果
void inOrder(TreeNode*root,int &k){ // 中序遍历递归函数
if(root==nullptr) return; // 遇到空指针直接返回
inOrder(root->left,k); // 左子树递归
k--; // 访问结点并进行倒着计数
if(k==0) res=root;
inOrder(root->right,k); // 右子树递归
}
TreeNode* KthNode(TreeNode* pRoot, int k) {
inOrder(pRoot, k); // 调用中序遍历
return res; // 返回指针
}
}; 方法二:非递归中序遍历
非递归的方案需要维护一个栈,对栈的操作同样要理解成递归的方式
- 沿着左子树一直入栈到底
- 取栈顶元素访问
- 对当前栈顶元素的右子树进行同样方式的访问
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k) {
TreeNode* res = NULL;
stack<TreeNode* > s; // 维护一个栈
int n = 0; // 初始化计数器
TreeNode* cur = pRoot; // 迭代指针初始指向根节点
while(!s.empty() || cur) { // 判断条件:栈非空 或 cur非空
while(cur){ // 沿着左子树全部进栈
s.push(cur);
cur = cur -> left;
}
cur = s.top(); // 取栈顶元素
s.pop();
n++; // 计数器+1
if(n == k) { // 判断是否为第k个元素
res = cur;
return res;
}
cur = cur->right; // 迭代指针指向取出来的栈顶元素的右侧孩子
}
return res;
}
}; 两种方法的复杂度计算
- 时间复杂度:O(n),访问每个节点
- 空间复杂度:O(n),维护栈的空间深度
不会做题写的题解 文章被收录于专栏
哎呀我好笨呀,一不小心又不会了一道题

