C++版本来了。。。。参考了评论区大佬和CSDN里面博主的做法, 思路是写死磕递归,然后再用栈模拟递归的流程,代码相当简洁,理解起来还可以。 //递归 //采用递归的方式,不断递归深入根节点的左孩子,直到碰到空节点为止,然后回溯输出当前节点。再以同样的方式递归遍历其右孩子。在此期间,每访问一个节点,我们都对k进行减一操作,直到k为0,说明该节点即为第k个节点。 class Solution { public: int m; TreeNode* ans; void dfs(TreeNode* p){ if(!p || m < 1) return;//不满足条件直接返回NULL/每次递归出口: dfs(p -> left);//走到了最左边结点,到空不继续递归,该节点左右走完了回溯上一层 if(m == 1) ans = p;//最左边结点 / m-到1的时候,当前结点就是第m小 if(--m > 0) dfs(p -> right);// 右子树同样处理/遍历该节点的右节点 (左中右) } TreeNode* KthNode(TreeNode* p, unsigned int k){ ans = NULL; m = k;//初始化 ans=NULL 不满足条件返回NULL dfs(p); return ans; } }; //非递归 死扣递归很多时候还是有必要的,它不仅是一种优美的思路,简洁的代码,更体现的是对函数不断调入与回溯这一过程的整体把握,基于整个递归程序流程的理解再去写非递归会更简单。递归的过程其实就是函数不断的调入,在计算机中每一个函数都是一个栈帧,函数的调入与完成对应入栈与出栈。 //非递归版中序遍历,可以利用栈来模拟递归遍历,首先根入栈,然后令根节点的左孩子不断入栈直到为空,弹出栈顶,令其右孩子入栈,重复以上操作,直到遍历结束或者访问第k个节点为止。 class Solution { public: TreeNode* KthNode(TreeNode* pRoot,unsigned int k) { if(!pRoot) return nullptr; stack<TreeNode *> res; TreeNode* p =pRoot; while(!res.empty() || p ){//res是空 and 遍历到空节点 while(p){ res.push(p); p = p->left; } TreeNode* node = res.top(); res.pop(); if((--k)==0) return node; p = node->right; } return nullptr; } };