二叉搜索树的第k个结点
思路
采用中序遍历,天然的就是升序,则找到中序遍历的第k个节点就行~~~
写法1 – 递归
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
// 考虑二叉搜索数的性质,中序遍历的结果就是升序的,那么遍历到第k个节点就行。
public class Solution {
int n = 0;
TreeNode res = null;
TreeNode KthNode(TreeNode pRoot, int k)
{
mid(pRoot, k);
return res;
}
void mid(TreeNode node, int k){
if(k < 0 || node == null) return;
// 先判断考虑左子树
mid(node.left,k);
n++;
// 判断自己;
if(n == k) {
res = new TreeNode(node.val);
return ;
}
// 判断右子树。
mid(node.right, k);
}
}
写法二 – 迭代
把递归改写成迭代的写法;用栈来存储遍历的节点。
import java.util.Stack;
// 考虑二叉搜索数的性质,中序遍历的结果就是升序的,那么遍历到第k个节点就行。
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
if (pRoot == null || k < 0) return null;
TreeNode cur = pRoot;
TreeNode res = null;
int n = 0;
Stack<TreeNode> stack = new Stack<>();
while(cur != null || !stack.empty()){
while(cur != null){
stack.push(cur);
cur = cur.left; // 循环结束,cur指向null
}
cur = stack.pop(); // 找完左子树,找右子树,要先定位最左子树。
n++;// k是从第一开始算的....
if(n == k){
res = new TreeNode(cur.val);
break;
}
cur = cur.right;
}
return res;
}
}
二叉树的Morris遍历算法
Morris一种中序遍历法,能以O(1)的空间复杂度O(n)的时间复杂度实现二叉树的中序遍历。
核心是找某个节点的前序节点。
算法步骤:
1, 根据当前节点,找到其前序节点,如果前序节点的右孩子是空,那么把前序节点的右孩子指向当前节点,然后进入当前节点的左孩子。
2. 如果当前节点cur的左孩子为空,打印当前节点,然后进入cur的右孩子。
3. 如果当前节点的前序节点其右孩子指向了它本身,那么把前序节点的右孩子设置为空,打印当前节点,然后进入右孩子。
// 考虑二叉搜索数的性质,中序遍历的结果就是升序的,那么遍历到第k个节点就行。
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
int n = 0;
if(pRoot == null || k < 1) return null;
TreeNode res = null;
TreeNode cur = pRoot;
while(cur != null){ // 如果当前节点不为空,去找它的前节点。其前序应该是它的左孩子的最右节点。
if(cur.left == null){ // 如果它的左子树为空,证明cur是中序中首先被访问的节点,下一个节点会出去访问它的右孩子。
n++; // 记录cur被访问了;
if(n == k){
res = new TreeNode(cur.val);
break;
}
cur = cur.right;
}else{ // 如果有左子树,则要去找左子树的最右孩子。
TreeNode pre = cur.left; // 记录cur的前序节点。
// 找左子树的最右节点,该节点就是cur的前序节点!!!
// 另外,morris需要在第一次找前序节点的是由,如果该前序节点的右孩子为空,需要让右孩子指向cur;
while(pre.right != null && pre.right != cur){
pre = pre.right;
}
if(pre.right == null){
pre.right = cur; // 让左孩子的最右孩子指向cur;
cur = cur.left;
}
if(pre.right == cur){
n++;
if(n == k){
res = new TreeNode(cur.val);
break;
}
pre.right = null;
cur = cur.right;
}
}
}
return res;
}
}