本篇介紹一下關於二叉樹結構很基礎的面試題,基礎到什麼程度呢,引用谷歌的話術: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off.(連二叉樹翻轉你都不會,你還玩個毛!)進一步說明了學習數據結構與算法的重要性——爲了避免被谷歌鄙視-.-node
Invert a binary tree.面試
Example:算法
Input:bash
Output:數據結構
Trivia: This problem was inspired by this original tweet by Max Howell:學習
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off.
複製代碼
翻轉一棵二叉樹。ui
示例:this
輸入:編碼
輸出:spa
備註: 這個問題是受到 Max Howell 的原問題啓發:
谷歌:
咱們谷歌90%的工程師使用你寫的軟件(Homebrew),可是你卻沒法在面試時在白板上寫出翻轉二叉樹這道題,這...(連二叉樹翻轉你都不會,你還玩個毛!)
複製代碼
理解遞歸思想的條件下很容易想到解題思路,固然可能有人會有疑問,那什麼狀況下知道使用遞歸呢,有個最簡單的辦法若是算法裏須要重複循環用同一個思路執行獲得結果,那麼必然可使用遞歸。進行翻轉本質上能夠拆分爲兩步遞歸,遞歸翻轉左子樹和遞歸翻轉右子樹分。不管是否使用遞歸本質思想是一致的,使用非遞歸的方式則須要藉助使用棧或者隊列的結構進行存儲未交換的子節點。
本質思想是,左右節點進行交換,循環翻轉每一個節點的左右子節點,將未翻轉的子節點存入棧中,循環直到棧裏全部節點都循環交換完爲止。方法一僞代碼:
本質思想是,左右節點進行交換,循環翻轉每一個節點的左右子節點,將未翻轉的子節點存入隊列中,循環直到棧裏全部節點都循環交換完爲止。
一、判斷根結點是否爲空,爲空則返回null;
二、新建棧(隊列),用於節點存儲,初始存入根節點到棧(隊列)裏;
三、while循環,棧(隊列)爲空時結束循環;
i.出棧(隊列)一個節點,將該節點的左右子節點交互;
ii.判斷左右子節點是否爲null,非null則繼續將左右節點入棧(隊列);
四、循環交換結束,返回根節點;
複製代碼
本質思想也是左右節點進行交換,交換前遞歸調用對根結點的左右節點分別進行處理,保證交換前左右節點已經翻轉。
一、判斷根結點是否爲空,爲空則返回null;
二、交換跟節點的左右節點;
三、遞歸交互左右子樹;
複製代碼
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
final TreeNode node = stack.pop();
final TreeNode left = node.left;
node.left = node.right;
node.right = left;
if(node.left != null) {
stack.push(node.left);
}
if(node.right != null) {
stack.push(node.right);
}
}
return root;
}
複製代碼
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
TreeNode left = node.left;
node.left = node.right;
node.right = left;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return root;
}
複製代碼
public TreeNode invertTree(TreeNode node) {
if (node == null) {
return null;
}
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
invertTree(node.left);
invertTree(node.right);
return node;
}
複製代碼
對比三種實現代碼執行結果會發現,三種方法最終leetcode測評的效率都是100%,可是方法一的runtime時間確實1ms,而方法二和方法三的runtime倒是0ms。爲何一樣的算法思想使用不一樣的數據結構,使用Stack比使用LinkedList要慢呢?這即是本篇的彩蛋!
華爲面試題中的二叉樹翻轉使用非遞歸實現是一道基礎知識題,二叉樹的左右子節點翻轉的非遞歸實現也包含了DFS和BFS的使用,最後若是以爲本篇對你有所幫助,給個贊吧0.0~