二叉搜尋樹中找出比K大的最小的那個數
阿新 • • 發佈:2019-01-31
這是一道面試的演算法題,題目不難,但是在面試的時候是要求直接在白板上寫程式,感覺自己還是弱爆了。第一次體驗這種面試方式,雖然被虐,但是感覺還是挺好的,這方面的經驗還是需要積累。
題目: 在一個二叉搜尋樹種查詢比某個數(K)大數中最小的那個。
先把二叉樹相關的構造程式碼貼上,下面是二叉樹的節點定義。
/**
*節點
*/
public class Node {
private int data;
private Node lChild, rChild;
public Node (int data){
this.data = data;
this .lChild = null;
this.rChild = null;
}
public Node(int data, Node l, Node r){
this.data = data;
this.rChild = r;
this.lChild = l;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLChild() {
return lChild;
}
public void setLChild(Node lChild) {
this.lChild = lChild;
}
public Node getRChild() {
return rChild;
}
public void setRChild(Node rChild) {
this.rChild = rChild;
}
}
下面是二叉樹定義, 構造,以及三種遍歷方法。
public class BinTree {
private Node root;
public BinTree(){
root = null;
}
/**
* 建立搜尋二叉樹
* @param node
* @param data
*/
private void BuildBinTree(Node node, int data){
if(root == null){
root = new Node(data);
}else{
if(data > node.getData()){
if(node.getRChild() == null)
node.setRChild(new Node(data));
else
BuildBinTree(node.getRChild(), data);
}else{
if(node.getLChild() == null)
node.setLChild(new Node(data));
else
BuildBinTree(node.getLChild(), data);
}
}
}
public void BuildBinTree(int[] arr){
for(int i:arr)
BuildBinTree(root, i);
}
public Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
/**
* 遞迴_先序遍歷
* @param node
*/
public void PreOrderTraverse(){
if(root != null){
System.out.print("先序遍歷:");
this.PreOrderTraverse(root);
System.out.println();
}else
System.out.println("Error! This tree is empty...");
}
private void PreOrderTraverse(Node node){
if(node != null){
System.out.print(node.getData()+" ");
PreOrderTraverse(node.getLChild());
PreOrderTraverse(node.getRChild());
}
}
/**
* 遞迴_中序遍歷
* @param node
*/
public void InOrderTraverse(){
if(root != null){
System.out.print("中序遍歷:");
this.InOrderTraverse(root);
System.out.println();
}else
System.out.println("Error! This tree is empty...");
}
private void InOrderTraverse(Node node){
if(node != null){
InOrderTraverse(node.getLChild());
System.out.print(node.getData()+" ");
InOrderTraverse(node.getRChild());
}
}
首先對於這個題目,最小白的方法就是把二叉樹變成一個有序陣列(中序遍歷)O(n),在有序陣列中進行二分查詢O(logn)。
這裡重點是第二種方法,在樹結構中進行查詢, 感覺這個問題,和二叉樹中插入新節點的過程是類似的,大致如下:
- 定義節點node, 並將根節點賦值給node;
- 如果node.data > K, 將node.data暫存在臨時變數中,並轉向左子樹;
- 如果node.data < K , 轉向右子樹;
- 重複步驟2和步驟3直到葉子節點
這裡需要注意的是,必須要遍歷到葉子節點,這個過程其實就是一個二分查詢的過程,複雜度O(logn).這裡我設定了一個標記,就是如果是空樹則返回 0.
/**
* 查詢比key大的最小的數
* @param tree:二叉搜尋樹
* @param key:要查詢的數
* @return:返回最終值
*/
public static int FindMinOfMax(BinTree tree, int key){
Node node = tree.getRoot();
int temp = 0;
if(node == null)
return temp;
while(node != null){
if(node.getData() > key)
temp = node.getData();
if(node.getData() > key){
node = node.getLChild();
}else{
node = node.getRChild();
}
if(node == null)
break;
}
return temp;
}