【剑指offer】20.二叉搜索树的第k个节点
总目录:
1.问题描述
给定一棵结点数为n 二叉搜索树,请找出其中的第 k 小的TreeNode结点值。
1.返回第k小的节点值即可
2.不能查找的情况,如二叉树为空,则返回-1,或者k大于n等等,也返回-1
3.保证n个节点的值不一样
数据范围: 0≤n≤1000,0≤k≤1000,树上每个结点的值满足0≤val≤1000
进阶:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(n),时间复杂度 O(n)
如输入{5,3,7,2,4,6,8},3时,二叉树{5,3,7,2,4,6,8}如下图所示:
该二叉树所有节点按结点值升序排列后可得[2,3,4,5,6,7,8],所以第3个结点的结点值为4,故返回对应结点值为4的结点即可。
2.问题分析
1递归,压栈拉来储值,因为是有序的搜索树,必须使用中序搜索
2粗暴迭代,逻辑较为复杂,但这种中序迭代方式值得学习,同样也必须是中序搜索
3.代码实例
递归
1 /** 2 * struct TreeNode { 3 * int val; 4 * struct TreeNode *left; 5 * struct TreeNode *right; 6 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 /** 12 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 13 * 14 * 15 * @param proot TreeNode类 16 * @param k int整型 17 * @return int整型 18 */ 19 stack<int> sp; 20 int searchRet = -1; 21 int recurve(TreeNode* root, int k) { 22 //中止条件 23 if (!root) { 24 return -1; 25 } 26 27 //递归调用,中序搜索 28 searchRet = recurve(root->left, k); 29 if (searchRet >= 0) { 30 return searchRet; 31 } 32 33 //本层逻辑 34 sp.push(root->val); 35 if (sp.size() == k) { 36 return sp.top(); 37 } 38 39 //递归调用 40 searchRet = recurve(root->right, k); 41 if (searchRet >= 0) { 42 return searchRet; 43 } 44 45 return searchRet; 46 } 47 48 int KthNode(TreeNode* proot, int k) { 49 if (k <= 0) { 50 return -1; 51 } 52 return recurve(proot, k); 53 } 54 };
粗暴迭代
1 class Solution { 2 public: 3 int KthNode(TreeNode* proot, int k) { 4 if(proot == NULL) 5 return -1; 6 //记录遍历了多少个数 7 int count = 0; 8 TreeNode* p = NULL; 9 //用栈辅助建立中序 10 stack<TreeNode*> s; 11 while(!s.empty() || proot != NULL){ 12 while (proot != NULL) { 13 s.push(proot); 14 //中序遍历每棵子树从最左开始 15 proot = proot->left; 16 } 17 p = s.top(); 18 s.pop(); 19 count++; 20 //第k个直接返回 21 if(count == k) 22 return p->val; 23 proot = p->right; 24 } 25 //没有找到 26 return -1; 27 } 28 };