剑指offer 54-二叉搜索树的第k个节点 C++

16 篇文章 0 订阅

题目描述
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

思路1:对于二叉搜索树,它的中序遍历数值是递增排序的。先进行递归中序,存入数组,然后从数组中取出第k大的数。尤其注意边界条件,即k与二叉树节点数的大小!若k>总节点数,就返回nullpter。

class Solution {
public:
	TreeNode* KthNode(TreeNode* pRoot, int k)
	{
        if (pRoot == nullptr || k<=0)
			return nullptr;
		vector<TreeNode*> arr;
		inOrder(pRoot, arr);
		if (k > arr.size())   //判断k与数组元素大小
			return nullptr;
		return arr[k - 1];
	}
	void inOrder(TreeNode* pRoot, vector<TreeNode*>& arr) {  //中序遍历,存入数组中
		if (pRoot == nullptr) 
			return;
		inOrder(pRoot->left, arr);
		arr.push_back(pRoot);
		inOrder(pRoot->right, arr);
	}
};

思路2:定义一个TreeNode*来存储第k个节点,但也是完全遍历完所有节点后再退出递归。

class Solution {
public:
	TreeNode* res = nullptr;
	int count = 0;
	TreeNode* KthNode(TreeNode* pRoot, int k)
	{
		if (pRoot == nullptr) 
			return nullptr;
		KthNode(pRoot->left, k);
		if (++count == k) 
			res = pRoot;
        KthNode(pRoot->right, k);  
		return res;
	}
};

思路3:优化思路2 解法,当找到第k个节点时就跳出递归,而不必对所有值进行运算,降低时间复杂度。

class Solution {
public:
	TreeNode* res = nullptr;
	int count = 0;
	TreeNode* KthNode(TreeNode* pRoot, int k)
	{
		if (pRoot == nullptr) 
			return nullptr;
		KthNode(pRoot->left, k);
		if (++count == k) 
			res = pRoot;
		if(count<k)  //加上if(count<k)判断后,如果满足count==k了就直接跳出递归!如果直接写成KthNode(pRoot->right, k);会遍历完所有节点,再退出
        	KthNode(pRoot->right, k);   
		return res;
	}
};

也可以写成如下方式:
对于 if (node != nullptr) return node; 的理解:

如果没有if(node != null)这句话 那么那个root就是返回给上一级的父结点的,而不是递归结束的条件了,有了这句话过后,一旦返回了root,那么node就不会为空了,就一直一层层的递归出去到结束了。

class Solution {
public:
	int count = 0;
	TreeNode* KthNode(TreeNode* pRoot, int k)
	{
		if (pRoot == nullptr || k <= 0)
			return nullptr;
		TreeNode* node = nullptr;
		node = KthNode(pRoot->left, k);
		if (node != nullptr)  //递归结束的条件。当count<k时,node=nullptr;只有当count==k时,node==第k个pRoot,便返回。
			return node;
		count++;
		if (count == k)   //当count==k时,找到了对应节点,但是递归并没有结束,所以需要将结果通过node逐层返回。
			return pRoot;
		node = KthNode(pRoot->right, k);
		if (node != nullptr)
			return node;
	}
};

思路4:DFS,使用栈,中序遍历的非递归方式。

class Solution {
public:
	TreeNode* KthNode(TreeNode* pRoot, int k)
	{
		if (pRoot == nullptr || k <= 0)
			return nullptr;
		stack<TreeNode*> s;
        int count = 0;
		while (pRoot!=nullptr || !s.empty())
		{
			while (pRoot!=nullptr)
			{
                s.push(pRoot);
				pRoot = pRoot->left;  //将最左一条子树依次压入栈,后面根据左子树出栈顺序来判断并压入每一个节点对应的右子树
			}
			if (!s.empty()) {
				pRoot = s.top();
				s.pop();
				if (++count == k)  //当count == k,就返回并退出
					return pRoot;
				pRoot = pRoot->right;  //栈顶元素向右子树遍历
			}
		}
        return nullptr;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值