二叉搜索樹的第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;
}
}