1. 程式人生 > >二叉搜尋樹中找出比K大的最小的那個數

二叉搜尋樹中找出比K大的最小的那個數

這是一道面試的演算法題,題目不難,但是在面試的時候是要求直接在白板上寫程式,感覺自己還是弱爆了。第一次體驗這種面試方式,雖然被虐,但是感覺還是挺好的,這方面的經驗還是需要積累。

題目: 在一個二叉搜尋樹種查詢比某個數(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)。
這裡重點是第二種方法,在樹結構中進行查詢, 感覺這個問題,和二叉樹中插入新節點的過程是類似的,大致如下:

  1. 定義節點node, 並將根節點賦值給node;
  2. 如果node.data > K, 將node.data暫存在臨時變數中,並轉向左子樹;
  3. 如果node.data < K , 轉向右子樹;
  4. 重複步驟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;
    }