題目:
在二叉排序樹上面找出第3大的節點。
注意:不能把二叉樹全量存儲到另外的存儲空間,比如存儲到數組中,然後取出數組的第三個元素。
- 遞歸解法
import java.util.Stack;
public class Problem3 {
private static int count = 0;
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1, null, null);
TreeNode node3 = new TreeNode(3, null, null);
TreeNode node4 = new TreeNode(4, node3, null);
TreeNode node2 = new TreeNode(2, node1, node4);
TreeNode node8 = new TreeNode(8, null, null);
TreeNode root = new TreeNode(6, node2, node8);
System.out.println("遞歸求解");
TreeNode result1 = find1(root);
if (result1 != null) {
System.out.println(result1.value);
} else {
System.out.println("result1 is null");
}
System.out.println("非遞歸求解");
TreeNode result2 = find2(root);
if (result2 != null) {
System.out.println(result2.value);
} else {
System.out.println("result2 is null");
}
}
public static class TreeNode {
int value;
TreeNode left, right;
public TreeNode(int value, TreeNode left, TreeNode right) {
this.value = value;
this.left = left;
this.right = right;
}
};
/*
* 對二叉排序樹進行中序遍歷可以得到從小到大的序列
* 中序遍歷遞歸實現: 先中序遍歷左子樹,然後遍歷根節點,中序遍歷右子樹
* 本題解法:
* 使用逆序中序遍歷可以較快地得到第三大的元素
* 先逆中序遍歷右子樹,再讀取根結點,再逆序遍歷左子樹
*/
//遞歸寫法
private static TreeNode find1(TreeNode root) {
if (root != null) {
TreeNode r1 = find1(root.right);
if(r1 != null) {
//已找到第三最大
return r1;
}
if(count++ == 2) {
return root;
}
TreeNode r2 = find1(root.left);
if(r2 != null) {
//已找到第三最大
return r2;
}
}
return null;
}
//非遞歸寫法
private static TreeNode find2(TreeNode root) {
//二叉樹逆中序遍歷,右中左
//需要藉助一個棧
Stack<TreeNode> s = new Stack<>();
TreeNode p = root;//工作指針
int count2 = 0;//用於尋找第三大,計數器
while(p !=null || !s.isEmpty()){
//棧非空或者p非空時循環
if(p != null){
s.push(p);//根指針進棧
p = p.right;//遍歷右子樹
}else{
p = s.pop();//退棧並訪問
if(count2++ == 2){
// System.out.println(p.value);
return p;
}
p = p.left;//遍歷左子樹
}
}
return null;
}
}