成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

我的面試準(zhǔn)備過(guò)程--二叉樹(shù)(更新中)

Amio / 825人閱讀

摘要:寫(xiě)在最前面導(dǎo)師貪腐出逃美國(guó),兩年未歸,可憐了我。拿了小米和美團(tuán)的,要被延期,失效,工作重新找。把準(zhǔn)備過(guò)程紀(jì)錄下來(lái),共勉。

寫(xiě)在最前面

導(dǎo)師貪腐出逃美國(guó),兩年未歸,可憐了我。拿了小米和美團(tuán)的offer,要被延期,offer失效,工作重新找。把準(zhǔn)備過(guò)程紀(jì)錄下來(lái),共勉。

二叉樹(shù)的基礎(chǔ) 結(jié)點(diǎn)定義
public class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(int val){
        this.val = val;
    }
}
二叉樹(shù)的遍歷 前序遍歷

前序遍歷,遞歸法

public static void preorderTraversalRec(TreeNode root) {
    if(root == null){
        return;
    }

    System.out.print(root.val + " ");
    preorderTraversalRec(root.left);
    preorderTraversalRec(root.right);
}

前序遍歷,迭代法
思路:借助一個(gè)棧

public static void preorderTraversal(TreeNode root) {
    if(null == root){
        return;
    }

    Stack stack = new Stack<>();
    stack.push(root);

    while(!stack.empty()){
        TreeNode cur = stack.pop();

        System.out.println(cur.val);

        //后入先出,因而先壓右結(jié)點(diǎn),再壓左結(jié)點(diǎn)
        if(null != cur.right){
            stack.push(cur.right);
        }

        if(null != cur.left){
            stack.push(cur.left);
        }

    }
}

中序遍歷

中序遍歷,遞歸法

public static void inorderTraversalRec(TreeNode root) {
    if(null == root){
        return;
    }

    inorderTraversalRec(root.left);
    System.out.print(root.val + " ");
    inorderTraversalRec(root.right);

}

中序遍歷,迭代法

public static void inorderTraversal(TreeNode root) {
    if(null == root){
        return;
    }

    Stack stack = new Stack<>();
    TreeNode cur = root;

    while(true){
        while(cur != null){
            stack.push(cur);
            cur = cur.left;
        }

        if(stack.empty()){
            break;
        }

        cur = stack.pop();
        System.out.print(cur.val + " ");
        cur = cur.right;
    }

}

后序遍歷

后序遍歷,遞歸法

public static void postorderTraversalRec(TreeNode root) {
    if(null == root){
        return;
    }

    postorderTraversalRec(root.left);
    postorderTraversalRec(root.right);
    System.out.print(root.val + " ");
}

后序遍歷,迭代法

public static void postorderTraversal(TreeNode root){
    if(null == root){
        return;
    }

    Stack s = new Stack();
    Stack output = new Stack<>();

    s.push(root);
    while(!s.empty()){
        TreeNode cur = s.pop();
        output.push(cur);

        if(cur.left != null){
            s.push(cur.left);
        }

        if(cur.right != null){
            s.push(cur.right);
        }
    }

    while(!output.empty()){
        System.out.print(output.pop().val + " ");
    }
}

分層遍歷

public static void levelTraversal(TreeNode root) {
    if(null == root){
        return;
    }

    Queue queue = new LinkedList<>();
    queue.push(root);

    while(!queue.empty()){
        TreeNode cur = queue.removeFirst();
        System.out.print(cur.val + " ");

        if(cur.left != null){
            queue.add(cur.left);
        }

        if(cur.right != null){
            queue.add(cur.right);
        }
    }
}

求二叉樹(shù)結(jié)點(diǎn)的個(gè)數(shù)

遞歸解法 時(shí)間復(fù)雜度O(n)

public static int getNodeNumRec(TreeNode root){
    if(null != root){
        return 0;
    }

    return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;
}

迭代解法 時(shí)間復(fù)雜度O(n)
思路:與層級(jí)遍歷相同,遍歷的過(guò)程中紀(jì)錄結(jié)點(diǎn)數(shù)

public static int getNodeNum(TreeNode root){
    if(null != root){
        return 0;
    }

    int count = 1;
    Queue queue = LinkedList<>();
    queue.add(root);

    while(!queue.empty()){
        TreeNode cur = queue.remove();

        if(cur.left != null){
            queue.add(cur.left);
            count++;
        }

        if(cur.right != null){
            queue.add(cur.right);
            count++;
        }
    }

    return count;
}

求二叉樹(shù)的深度(高度)

遞歸解法 時(shí)間復(fù)雜度O(n)

public static int getDepthRec(TreeNode root) {
    if(null != root){
        return 0;
    }

    int leftDepth = getDepthRec(root.left);
    int rightDepth = getDepthRec(root.right);
    return Math.max(leftDepth, rightDepth) + 1;
}

迭代解法 時(shí)間復(fù)雜度O(n)

public static int getDepth(TreeNode root){
    if(null != root){
        return 0;
    }

    int depth = 0;
    int curLevelNodes = 1;
    int nextLevelNodes = 0;

    Queue queue = new LinkedList<>();
    queue.add(root);

    while(!queue.empty()){
        TreeNode cur = queue.remove();
        curLevelNodes--;

        if(cur.left != null){
            nextLevelNodes++;
            queue.add(cur.left);
        }

        if(cur.right != null){
            nextLevelNodes++;
            queue.add(cur.right);
        }

        if(curLevelNodes == 0){
            depth++;
            curLevelNodes = nextLevelNodes;
            nextLevelNodes = 0;
        }
    }

    return depth;
}

求二叉樹(shù)第K層的節(jié)點(diǎn)個(gè)數(shù)

遞歸解法
思路:求以root為根的k層節(jié)點(diǎn)數(shù)目 等價(jià)于 求以root左孩子為根的k-1層(因?yàn)樯倭藃oot那一層)節(jié)點(diǎn)數(shù)目 加上 以root右孩子為根的k-1層(因?yàn)樯倭藃oot那一層)節(jié)點(diǎn)數(shù)目

public static int getNodeNumKthLevelRec(TreeNode root, int k) {
    if(null != root || k < 0){
        return 0;
    }

    if(k == 1){
        return 1;
    }

    int leftNodeNumKth = getNodeNumKthLevelRec(root.left, k - 1);
    int rightNodeNumKth = getNodeNumKthLevelRec(root.right, k - 1);
    return leftNodeNumKth + rightNodeNumKth;
}

迭代法
思路:與求解樹(shù)深度的解法相同,需要

public static int getNodeNumKthLevel(TreeNode root, int k){
    if(root == null || k < 0){
        return 0;
    }

    Queue queue = new LinkedList<>();
    queue.add(root);

    int curLevelNodes = 1;
    int nextLevelNodes = 0;

    while(!queue.empty && k > 0){
        TreeNode cur = queue.remove();
        curLevelNodes--;

        if(cur.left != null){
            queue.add(cur.left);
            nextLevelNodes++;
        }

        if(cur.right != null){
            queue.add(cur.right);
            nextLevelNodes++;
        }

        if(curLevelNodes == 0){
            curLevelNodes = nextLevelNodes;
            nextLevelNodes = 0;
            k--;
        }
    }

    return curLevelNodes;
}

求二叉樹(shù)中葉子節(jié)點(diǎn)的個(gè)數(shù)

迭代法

public static int getNodeNumLeaf(TreeNode root) {
    if(root == null){
        return 0;
    }

    Queue queue = new LinkedList<>();
    queue.add(root);

    int leafNodeNum = 0;

    while(!queue.empty()){
        TreeNode cur = queue.remove();

        if(cur.left != null){
            queue.add(cur.left);
        }

        if(cur.right != null){
            queue.add(cur.right);
        }

        if(cur.left == null && cur.right = null){
            leafNodeNum++;
        }
    }
    return leafNodeNum;
}

兩個(gè)二叉樹(shù)之間的關(guān)系 判斷兩棵二叉樹(shù)是否相同的樹(shù)。

遞歸法

public static boolean isSameRec(TreeNode r1, TreeNode r2) {
    if(r1 == null && r2 == null){
        return true;
    }

    if(r1 == null || r2 == null){
        return false;
    }

    if(r1.val != r2.val){
        return false;
    }

    boolean leftRes = isSameRec(r1.left, r2.left);
    boolean rightRes = isSameRec(r1.right, r2.right);

    return leftRes && rightRes;
}

迭代法
思路:遍歷一遍,比對(duì)即可

public static boolean isSame(TreeNode r1, TreeNode r2) {
    if(r1 == null && r2 == null){
        return true;
    }

    if(r1 == null || r2 == null){
        return false;
    }

    Stack s1 = new Stack<>();
    Stack s2 = new Stack<>();

    s1.push(r1);
    s2.push(r2);

    while(!s1.empty() && !s2.empty()){
        TreeNode n1 = s1.pop();
        TreeNode n2 = s2.pop();

        if(n1 == null && n2 == null){
            continue;
        }else if(n1 != null && n2 != null && n1.val == n2.val){
            s1.push(n1.right);
            s1.push(n1.left);
            s2.push(n2.right);
            s2.push(n2.left);
        }else{
            return false;
        }
    }
    return true;
 }

判斷二叉樹(shù)是不是平衡二叉樹(shù)

遞歸解法

思路:
(1)如果二叉樹(shù)為空,返回真
(2)如果二叉樹(shù)不為空,如果左子樹(shù)和右子樹(shù)都是AVL樹(shù)并且左子樹(shù)和右子樹(shù)高度相差不大于1,返回真,其他返回假
public static boolean isAVLRec(TreeNode root) {
    if(root == null){
        return true;
    }

    if(Math.abs(getDepthRec(root.left) - getDepthRec(root.right)) > 1){
        return false;
    }

    return isAVLRec(root.left) && isAVLRec(root.right);
}

樹(shù)的鏡像 判斷兩個(gè)樹(shù)是否互相鏡像
    public static boolean isMirrorRec(TreeNode r1, TreeNode r2){
   if(r1 == null && r2 == null){
       return true;
   }

   if(r1 == null || r2 == null){
       return false;
   }

   if(r1.val != r2.val){
       return false;
   }

   return isMirrorRec(r1.left, r2.right) && isMirrorRec(r1.right, r2.left);
    }
求樹(shù)的鏡像

遞歸解法
(1)如果二叉樹(shù)為空,返回空
(2)如果二叉樹(shù)不為空,求左子樹(shù)和右子樹(shù)的鏡像,然后交換左子樹(shù)和右子樹(shù)

破壞原來(lái)的樹(shù)

public static TreeNode mirrorRec(TreeNode root) {
if(root == null){
   return null;
}

TreeNode left = mirrorRec(root.left);
TreeNode right = mirrorRec(root.right);

root.left = right;
root.right = left;
return root;
}

2.保存原來(lái)的樹(shù)

public static TreeNode mirrorCopyRec(TreeNode root) {
    if(root == null){
        return null;
    }

    TreeNode newRoot = new TreeNode(root.val);
    newRoot.left = mirrorCopyRec(root.right);
    newRoot.right = mirrorCopyRec(root.left);

    return newRoot;

}

迭代解法

破壞原來(lái)的樹(shù)

public static void mirror(TreeNode root) {
    if(root == null){
        return;
    }

    Stack stack = new Stack();
    stack.push(root);

    while(!stack.empty()){
        TreeNode cur = stack.pop();

        TreeNode tmp = cur.left;
        cur.left = cur.right;
        cur.right = tmp;

        if(cur.left != null){
            stack.push(cur.left);
        }

        if(cur.right != null){
            stack.push(cur.right);
        }
    }
}

不能破壞原來(lái)的樹(shù),返回一個(gè)新的鏡像樹(shù)

public static TreeNode mirrorCopy(TreeNode root){
    if(root == null){
        return null;
    }

    Stack stack = new Stack<>();
    Stack newStack = new Stack<>();
    stack.push(root);
    TreeNode newRoot = new TreeNode(root.val);
    newStack.push(newRoot);

    while(!stack.empty()){
        TreeNode cur = stack.pop();
        TreeNode newCur = newStack.pop();

        if(cur.left != null){
            stack.push(cur.left);
            newCur.right = new TreeNode(cur.left.val);
            newStack.push(newCur.right);
        }

        if(cur.right != null){
            stack.push(cur.right);
            newCur.left = new TreeNode(cur.right.val);
            newStack.push(newCur.left);
        }
    }
    return newRoot;
}

求二叉樹(shù)中兩個(gè)節(jié)點(diǎn)的最低公共祖先節(jié)點(diǎn)

遞歸法
思路:1. 如果其中一個(gè)結(jié)點(diǎn)為根結(jié)點(diǎn),則返回根結(jié)點(diǎn)

如果一個(gè)左子樹(shù)找到,一個(gè)在右子樹(shù)找到,則說(shuō)明root是唯一可能的最低公共祖先

其他情況是要不然在左子樹(shù)要不然在右子樹(shù)

public static TreeNode getLastCommonParentRec(TreeNode root, TreeNode n1, TreeNode n2) {
    if (root == null || n1 == null || n2 == null) {
        return null;
    }

    if(root.equals(n1) || root.equals(n2)){
        return root;
    }

    TreeNode commonInLeft = getLastCommonParentRec(root.left, n1, n2);
    TreeNode commonInRight = getLastCommonParentRec(root.right, n1, n2);
    if(commonInLeft != null && commonInRight != null){
        return root;
    }

    if(commonInLeft == null){
        return commonInRight;
    }

    if(commonInRight == null){
        return commonInLeft;
    }
    return root;
}

迭代法

public static TreeNode getLastCommonParent(TreeNode root, TreeNode n1, TreeNode n2){
    if(root == null || n1 == null || n2 == null){
        return null;
    }

    List list1= new ArrayList<>();
    List list2 = new ArrayList<>();

    boolean res1 = getNodePath(root, n1, list1);
    boolean res2 = getNodePath(root, n2, list2);

    if(!res1 || !res2){
        return null;
    }

    Iterator iter1 = list1.iterator();
    Iterator iter2 = list2.iterator();
    TreeNode last = null;

    while(iter1.hasNext() && iter2.hasNext()){
        TreeNode tmp1 = iter1.next();
        TreeNode tmp2 = iter2.next();

        if(tmp1 == tmp2){
            last = tmp1;
        }else{
            break;
        }
    }
    return last;
}

private static boolean getNodePath(TreeNode root, TreeNode n, List path){
    if(root == null){
        return false;
    }

    path.add(root);
    if(root == n){
        return true;
    }

    boolean found = false;
    found = getNodePath(root.left, n, path);

    if(!found){
        found = getNodePath(root.right, n, path);
    }

    if(!found){
        path.remove(root);
    }

    return found;
}

本章參考http://blog.csdn.net/fightfor...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70112.html

相關(guān)文章

  • 前端該如何準(zhǔn)備數(shù)據(jù)結(jié)構(gòu)和算法?

    摘要:很多前端同學(xué)在看到數(shù)據(jù)結(jié)構(gòu)和算法后會(huì)有一定的抵觸心理,或者嘗試去練習(xí),但是被難倒,從而放棄。本文選擇的數(shù)據(jù)結(jié)構(gòu)和算法的類別均是出現(xiàn)頻率最高,以及應(yīng)用最廣的類別。面試這是非?,F(xiàn)實(shí)的一點(diǎn),也是很多前端學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)和算法的原因。 一、導(dǎo)讀 據(jù)我了解,前端程序員有相當(dāng)一部分對(duì)數(shù)據(jù)結(jié)構(gòu)和算法的基礎(chǔ)概念都不是很清晰,這直接導(dǎo)致很多人在看到有關(guān)這部分的內(nèi)容就會(huì)望而卻步。 實(shí)際上,當(dāng)你了解了數(shù)據(jù)結(jié)構(gòu)和...

    simon_chen 評(píng)論0 收藏0
  • 使用JavaScript完成叉樹(shù)的一些基本操作

    摘要:另外,由于篇幅有限,本篇的重點(diǎn)在于二叉樹(shù)的常見(jiàn)算法以及實(shí)現(xiàn)。常見(jiàn)的二叉樹(shù)實(shí)現(xiàn)代碼之前寫(xiě)過(guò)相關(guān)的文章,是關(guān)于如何創(chuàng)建及遍歷二叉樹(shù)的,這里不再贅述。同時(shí)我們注意到,在二叉樹(shù)深度比較大的時(shí)候,我們光是比較左右是不夠的。 本篇為復(fù)習(xí)過(guò)程中遇到過(guò)的總結(jié),同時(shí)也給準(zhǔn)備面試的同學(xué)一份參考。另外,由于篇幅有限,本篇的重點(diǎn)在于二叉樹(shù)的常見(jiàn)算法以及實(shí)現(xiàn)。 常見(jiàn)的二叉樹(shù)實(shí)現(xiàn)代碼 之前寫(xiě)過(guò)相關(guān)的文章,是關(guān)于如...

    YPHP 評(píng)論0 收藏0
  • LeetCode 攻略 - 2019 年 7 月下半月匯總(100 題攻略)

    摘要:月下半旬攻略道題,目前已攻略題。目前簡(jiǎn)單難度攻略已經(jīng)到題,所以后面會(huì)調(diào)整自己,在刷算法與數(shù)據(jù)結(jié)構(gòu)的同時(shí),攻略中等難度的題目。 Create by jsliang on 2019-07-30 16:15:37 Recently revised in 2019-07-30 17:04:20 7 月下半旬攻略 45 道題,目前已攻略 100 題。 一 目錄 不折騰的前端,和咸魚(yú)有什么區(qū)別...

    tain335 評(píng)論0 收藏0
  • 準(zhǔn)備下次編程面試前你應(yīng)該知道的數(shù)據(jù)結(jié)構(gòu)

    摘要:以下內(nèi)容編譯自他的這篇準(zhǔn)備下次編程面試前你應(yīng)該知道的數(shù)據(jù)結(jié)構(gòu)瑞典計(jì)算機(jī)科學(xué)家在年寫(xiě)了一本書(shū),叫作算法數(shù)據(jù)結(jié)構(gòu)程序。 國(guó)外 IT 教育學(xué)院 Educative.io 創(chuàng)始人 Fahim ul Haq 寫(xiě)過(guò)一篇過(guò)萬(wàn)贊的文章《The top data structures you should know for your next coding interview》,總結(jié)了程序員面試中需要掌...

    desdik 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<