摘要:寫在最前面導師貪腐出逃美國,兩年未歸,可憐了我。拿了小米和美團的,要被延期,失效,工作重新找。把準備過程紀錄下來,共勉。
寫在最前面
導師貪腐出逃美國,兩年未歸,可憐了我。拿了小米和美團的offer,要被延期,offer失效,工作重新找。把準備過程紀錄下來,共勉。
二叉樹的基礎 結點定義public class TreeNode{ int val; TreeNode left; TreeNode right; public TreeNode(int val){ this.val = val; } }二叉樹的遍歷 前序遍歷
前序遍歷,遞歸法
public static void preorderTraversalRec(TreeNode root) { if(root == null){ return; } System.out.print(root.val + " "); preorderTraversalRec(root.left); preorderTraversalRec(root.right); }
前序遍歷,迭代法
思路:借助一個棧
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); //后入先出,因而先壓右結點,再壓左結點 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; } Stacks = 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求二叉樹結點的個數(shù)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); } } }
遞歸解法 時間復雜度O(n)
public static int getNodeNumRec(TreeNode root){ if(null != root){ return 0; } return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1; }
迭代解法 時間復雜度O(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; }
遞歸解法 時間復雜度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; }
迭代解法 時間復雜度O(n)
public static int getDepth(TreeNode root){ if(null != root){ return 0; } int depth = 0; int curLevelNodes = 1; int nextLevelNodes = 0; Queue求二叉樹第K層的節(jié)點個數(shù)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; }
遞歸解法
思路:求以root為根的k層節(jié)點數(shù)目 等價于 求以root左孩子為根的k-1層(因為少了root那一層)節(jié)點數(shù)目 加上 以root右孩子為根的k-1層(因為少了root那一層)節(jié)點數(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; }
迭代法
思路:與求解樹深度的解法相同,需要
public static int getNodeNumKthLevel(TreeNode root, int k){ if(root == null || k < 0){ return 0; } Queue求二叉樹中葉子節(jié)點的個數(shù)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; }
迭代法
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; }
遞歸法
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; }
迭代法
思路:遍歷一遍,比對即可
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; }
遞歸解法
思路: (1)如果二叉樹為空,返回真 (2)如果二叉樹不為空,如果左子樹和右子樹都是AVL樹并且左子樹和右子樹高度相差不大于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); }樹的鏡像 判斷兩個樹是否互相鏡像
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); }求樹的鏡像
遞歸解法
(1)如果二叉樹為空,返回空
(2)如果二叉樹不為空,求左子樹和右子樹的鏡像,然后交換左子樹和右子樹
破壞原來的樹
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.保存原來的樹
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; }
迭代解法
破壞原來的樹
public static void mirror(TreeNode root) { if(root == null){ return; } Stackstack = 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); } } }
不能破壞原來的樹,返回一個新的鏡像樹
public static TreeNode mirrorCopy(TreeNode root){ if(root == null){ return null; } Stack求二叉樹中兩個節(jié)點的最低公共祖先節(jié)點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; }
遞歸法
思路:1. 如果其中一個結點為根結點,則返回根結點
如果一個左子樹找到,一個在右子樹找到,則說明root是唯一可能的最低公共祖先
其他情況是要不然在左子樹要不然在右子樹
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; } Listlist1= 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...
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70112.html
摘要:很多前端同學在看到數(shù)據(jù)結構和算法后會有一定的抵觸心理,或者嘗試去練習,但是被難倒,從而放棄。本文選擇的數(shù)據(jù)結構和算法的類別均是出現(xiàn)頻率最高,以及應用最廣的類別。面試這是非常現(xiàn)實的一點,也是很多前端學習數(shù)據(jù)結構和算法的原因。 一、導讀 據(jù)我了解,前端程序員有相當一部分對數(shù)據(jù)結構和算法的基礎概念都不是很清晰,這直接導致很多人在看到有關這部分的內容就會望而卻步。 實際上,當你了解了數(shù)據(jù)結構和...
摘要:另外,由于篇幅有限,本篇的重點在于二叉樹的常見算法以及實現(xiàn)。常見的二叉樹實現(xiàn)代碼之前寫過相關的文章,是關于如何創(chuàng)建及遍歷二叉樹的,這里不再贅述。同時我們注意到,在二叉樹深度比較大的時候,我們光是比較左右是不夠的。 本篇為復習過程中遇到過的總結,同時也給準備面試的同學一份參考。另外,由于篇幅有限,本篇的重點在于二叉樹的常見算法以及實現(xiàn)。 常見的二叉樹實現(xiàn)代碼 之前寫過相關的文章,是關于如...
摘要:月下半旬攻略道題,目前已攻略題。目前簡單難度攻略已經(jīng)到題,所以后面會調整自己,在刷算法與數(shù)據(jù)結構的同時,攻略中等難度的題目。 Create by jsliang on 2019-07-30 16:15:37 Recently revised in 2019-07-30 17:04:20 7 月下半旬攻略 45 道題,目前已攻略 100 題。 一 目錄 不折騰的前端,和咸魚有什么區(qū)別...
摘要:以下內容編譯自他的這篇準備下次編程面試前你應該知道的數(shù)據(jù)結構瑞典計算機科學家在年寫了一本書,叫作算法數(shù)據(jù)結構程序。 國外 IT 教育學院 Educative.io 創(chuàng)始人 Fahim ul Haq 寫過一篇過萬贊的文章《The top data structures you should know for your next coding interview》,總結了程序員面試中需要掌...
閱讀 2470·2023-04-25 21:41
閱讀 1647·2021-09-22 15:17
閱讀 1921·2021-09-22 10:02
閱讀 2433·2021-09-10 11:21
閱讀 2569·2019-08-30 15:53
閱讀 996·2019-08-30 15:44
閱讀 946·2019-08-30 13:46
閱讀 1125·2019-08-29 18:36