精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何才能夠翻轉二叉樹

新材料在線 ? 來源:代碼隨想錄 ? 作者:程序員Carl ? 2021-09-01 11:45 ? 次閱讀

這道題目是非常經典的題目,也是比較簡單的題目(至少一看就會)。

但正是因為這道題太簡單,一看就會,一些同學都沒有抓住起本質,稀里糊涂的就把這道題目過了。

如果做過這道題的同學也建議認真看完,相信一定有所收獲!

226.翻轉二叉樹題目地址:https://leetcode-cn.com/problems/invert-binary-tree/

翻轉一棵二叉樹。

這道題目背后有一個讓程序員心酸的故事,聽說 Homebrew的作者Max Howell,就是因為沒在白板上寫出翻轉二叉樹,最后被Google拒絕了。(真假不做判斷,權當一個樂子哈)

思路我們之前介紹的都是各種方式遍歷二叉樹,這次要翻轉了,感覺還是有點懵逼。

這得怎么翻轉呢?

如果要從整個樹來看,翻轉還真的挺復雜,整個樹以中間分割線進行翻轉,如圖:

可以發現想要翻轉它,其實就把每一個節點的左右孩子交換一下就可以了。

關鍵在于遍歷順序,前中后序應該選哪一種遍歷順序?(一些同學這道題都過了,但是不知道自己用的是什么順序)

遍歷的過程中去翻轉每一個節點的左右孩子就可以達到整體翻轉的效果。

注意只要把每一個節點的左右孩子翻轉一下,就可以達到整體翻轉的效果

這道題目使用前序遍歷和后序遍歷都可以,唯獨中序遍歷不行,因為中序遍歷會把某些節點的左右孩子翻轉了兩次!建議拿紙畫一畫,就理解了

那么層序遍歷可以不可以呢?依然可以的!只要把每一個節點的左右孩子翻轉一下的遍歷方式都是可以的!

遞歸法對于二叉樹的遞歸法的前中后序遍歷,已經在二叉樹:前中后序遞歸遍歷詳細講解了。

我們下文以前序遍歷為例,通過動畫來看一下翻轉的過程:

我們來看一下遞歸三部曲:

確定遞歸函數的參數和返回值

參數就是要傳入節點的指針,不需要其他參數了,通常此時定下來主要參數,如果在寫遞歸的邏輯中發現還需要其他參數的時候,隨時補充。

返回值的話其實也不需要,但是題目中給出的要返回root節點的指針,可以直接使用題目定義好的函數,所以就函數的返回類型為TreeNode*。

TreeNode* invertTree(TreeNode* root)

確定終止條件

當前節點為空的時候,就返回

if (root == NULL) return root;

確定單層遞歸的邏輯

因為是先前序遍歷,所以先進行交換左右孩子節點,然后反轉左子樹,反轉右子樹。

swap(root-》left, root-》right);

invertTree(root-》left);

invertTree(root-》right);

基于這遞歸三步法,代碼基本寫完,C++代碼如下:

class Solution {public

TreeNode* invertTree(TreeNode* root) {

if (root == NULL) return root;

swap(root-》left, root-》right); // 中

invertTree(root-》left); // 左

invertTree(root-》right); // 右

return root;

}

};

迭代法深度優先遍歷二叉樹:聽說遞歸能做的,棧也能做!中給出了前中后序迭代方式的寫法,所以本地可以很輕松的切出如下迭代法的代碼:

C++代碼迭代法(前序遍歷)

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

if (root == NULL) return root;

stack《TreeNode*》 st;

st.push(root);

while(!st.empty()) {

TreeNode* node = st.top(); // 中

st.pop();

swap(node-》left, node-》right);

if(node-》right) st.push(node-》right); // 右

if(node-》left) st.push(node-》left); // 左

}

return root;

}

};

如果這個代碼看不懂的話可以在回顧一下二叉樹:聽說遞歸能做的,棧也能做!。

我們在二叉樹:前中后序迭代方式的統一寫法中介紹了統一的寫法,所以,本題也只需將文中的代碼少做修改便可。

C++代碼如下迭代法(前序遍歷)

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

stack《TreeNode*》 st;

if (root != NULL) st.push(root);

while (!st.empty()) {

TreeNode* node = st.top();

if (node != NULL) {

st.pop();

if (node-》right) st.push(node-》right); // 右

if (node-》left) st.push(node-》left); // 左

st.push(node); // 中

st.push(NULL);

} else {

st.pop();

node = st.top();

st.pop();

swap(node-》left, node-》right); // 節點處理邏輯

}

}

return root;

}

};

如果上面這個代碼看不懂,回顧一下文章二叉樹:前中后序迭代方式的統一寫法。

廣度優先遍歷也就是層序遍歷,層數遍歷也是可以翻轉這棵樹的,因為層序遍歷也可以把每個節點的左右孩子都翻轉一遍,代碼如下:

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

queue《TreeNode*》 que;

if (root != NULL) que.push(root);

while (!que.empty()) {

int size = que.size();

for (int i = 0; i 《 size; i++) {

TreeNode* node = que.front();

que.pop();

swap(node-》left, node-》right); // 節點處理

if (node-》left) que.push(node-》left);

if (node-》right) que.push(node-》right);

}

}

return root;

}

};

如果對以上代碼不理解,或者不清楚二叉樹的層序遍歷,可以看這篇二叉樹:層序遍歷登場!

總結針對二叉樹的問題,解題之前一定要想清楚究竟是前中后序遍歷,還是層序遍歷。

二叉樹解題的大忌就是自己稀里糊涂的過了(因為這道題相對簡單),但是也不知道自己是怎么遍歷的。

這也是造成了二叉樹的題目“一看就會,一寫就廢”的原因。

針對翻轉二叉樹,我給出了一種遞歸,三種迭代(兩種模擬深度優先遍歷,一種層序遍歷)的寫法,都是之前我們講過的寫法,融匯貫通一下而已。

大家一定也有自己的解法,但一定要成方法論,這樣才能通用,才能舉一反三!

其他語言版本Java://DFS遞歸class Solution {

/**

* 前后序遍歷都可以

* 中序不行,因為先左孩子交換孩子,再根交換孩子(做完后,右孩子已經變成了原來的左孩子),再右孩子交換孩子(此時其實是對原來的左孩子做交換)

*/

public TreeNode invertTree(TreeNode root) {

if (root == null) {

return null;

}

invertTree(root.left);

invertTree(root.right);

swapChildren(root);

return root;

}

private void swapChildren(TreeNode root) {

TreeNode tmp = root.left;

root.left = root.right;

root.right = tmp;

}

}

//BFSclass Solution {

public TreeNode invertTree(TreeNode root) {

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

ArrayDeque《TreeNode》 deque = new ArrayDeque《》();

deque.offer(root);

while (!deque.isEmpty()) {

int size = deque.size();

while (size-- 》 0) {

TreeNode node = deque.poll();

swap(node);

if (node.left != null) {deque.offer(node.left);}

if (node.right != null) {deque.offer(node.right);}

}

}

return root;

}

public void swap(TreeNode root) {

TreeNode temp = root.left;

root.left = root.right;

root.right = temp;

}

}

Python遞歸法:前序遍歷:

class Solution:

def invertTree(self, root: TreeNode) -》 TreeNode:

if not root:

return None

root.left, root.right = root.right, root.left #中

self.invertTree(root.left) #左

self.invertTree(root.right) #右

return root

迭代法:深度優先遍歷(前序遍歷):

class Solution:

def invertTree(self, root: TreeNode) -》 TreeNode:

if not root:

return root

st = []

st.append(root)

while st:

node = st.pop()

node.left, node.right = node.right, node.left #中

if node.right:

st.append(node.right) #右

if node.left:

st.append(node.left) #左

return root

迭代法:廣度優先遍歷(層序遍歷):

import collections

class Solution:

def invertTree(self, root: TreeNode) -》 TreeNode:

queue = collections.deque() #使用deque()

if root:

queue.append(root)

while queue:

size = len(queue)

for i in range(size):

node = queue.popleft()

node.left, node.right = node.right, node.left #節點處理

if node.left:

queue.append(node.left)

if node.right:

queue.append(node.right)

return root

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    21

    文章

    2085

    瀏覽量

    73301
  • 代碼
    +關注

    關注

    30

    文章

    4670

    瀏覽量

    67764
  • 二叉樹
    +關注

    關注

    0

    文章

    74

    瀏覽量

    12283

原文標題:你真的會翻轉二叉樹么?

文章出處:【微信號:xincailiaozaixian,微信公眾號:新材料在線】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    怎么才能夠將正弦波的直流分量取出?

    請教怎么才能夠將正弦波的直流分量取出,(我用低通濾波之后噪聲很大)
    發表于 09-19 06:13

    指電極上覆蓋敏感材料的阻值計算

    覆蓋的敏感材料厚度超出指厚度時計算電阻,是否可以視作指電極指間電阻多個周期串聯后與超出指厚度部分敏感材料電阻并聯
    發表于 07-05 14:48

    Endpoint端點如何做才能夠達到不需要PC端手動IN就將數據往上推送?

    您好,我想問一下Endpoint端點如何做才能夠達到不需要PC端手動IN就將數據往上推送? 使用的是FX3芯片,其中我發現在鼠標HID范例中,它就是不需要電腦IN,只要在某一個GPIO口觸發之后
    發表于 05-27 08:29

    tle9879 hall電機啟動需要用手撥動一下才能轉動怎么解決?

    才能夠正常啟動運轉,否則就不轉動。 已經試著調試過啟動占空比,給定的速度,以及 pid參數,都不管用。 問下能夠得到指點一下,感謝!
    發表于 03-28 07:58

    哈夫曼編碼怎么算 哈夫曼編碼左邊是0還是1

    二叉樹,將出現頻率高的字符用較短的編碼表示,而出現頻率低的字符則用較長的編碼表示。通過這種方式,可以實現對數據進行高效的編碼和解碼。 下面我們將詳細介紹哈夫曼編碼的算法過程。 統計字符頻率 在進行哈夫曼編碼前,首先需
    的頭像 發表于 01-30 11:27 ?2068次閱讀

    instance是何時翻轉的?每次有多少instance在翻轉

    在run dynamic vectorless IR時,instance是何時翻轉的?每次有多少instance在翻轉
    的頭像 發表于 01-26 09:31 ?405次閱讀
    instance是何時<b class='flag-5'>翻轉</b>的?每次有多少instance在<b class='flag-5'>翻轉</b>?

    堆的實現思路

    什么是堆? 堆是一種 基于樹結構的數據結構,它是一棵二叉樹 ,具有以下兩個特點: 堆是一個完全二叉樹,即除了最后一層,其他層都是滿的,最后一層從左到右填滿。 堆中每個節點都滿足堆的特性,即父節點的值
    的頭像 發表于 11-24 16:02 ?331次閱讀
    堆的實現思路

    二叉樹的定義

    型結構 是一類重要的 非線性數據結構 ,其中以二叉樹最為常用,直觀來看,是以分支關系定義的層次結構。型結構在客觀世界中廣泛存在,比
    的頭像 發表于 11-24 15:57 ?1034次閱讀
    <b class='flag-5'>樹</b>與<b class='flag-5'>二叉樹</b>的定義

    OP-TEE安全存儲安全文件的格式

    時,默認情況下, 加密后的數據會被保存在/data/tee目錄中。 安全存儲功能使用 二叉樹的方式來 保存加密后的文件。 當第一次使用安全存儲功能創建用于保存敏感數據的安全文件時,OP-TEE將會在/data/tee目錄中生成兩個文件:dirf.db文件和以數字命名的文件。 dirf.db文
    的頭像 發表于 11-21 11:49 ?545次閱讀
    OP-TEE安全存儲安全文件的格式

    什么情況下需要布隆過濾器

    , gmail等郵箱垃圾郵件過濾功能 這幾個例子有一個共同的特點:如何判斷一個元素是否存在一個集合中? 常規思路 數組 鏈表 、平衡二叉樹、Trie Map (紅黑) 哈希表 雖然上面描述的這幾種數據結構配合常見的排序、
    的頭像 發表于 11-11 11:37 ?552次閱讀
    什么情況下需要布隆過濾器

    紅黑的特點及應用

    比起理解紅黑的原理,更重要的是理解紅黑的應用場景,因為某些應用場景的需要,紅黑才會應運而生。 紅黑的特點: 插入,刪除,查找都是O(logn)的復雜度。 紅黑
    的頭像 發表于 11-10 11:16 ?609次閱讀
    紅黑<b class='flag-5'>樹</b>的特點及應用

    為什么MySQL索引要用B+tree?

    紅黑是一種特化的 AVL(平衡二叉樹),都是在進行插入和刪除操作時通過特定操作保持二叉查找的平衡; 若一棵
    發表于 10-30 14:41 ?170次閱讀

    文件系統-多二叉樹的轉化

    在這一節中,我們來學習如何使用程序來實現一棵文件。在上一節中,我們了解到使用文件的方式來整合計算機中所有的資源,而這一棵文件則是一棵多
    的頭像 發表于 10-11 10:06 ?768次閱讀
    文件系統-多<b class='flag-5'>叉</b><b class='flag-5'>樹</b>與<b class='flag-5'>二叉樹</b>的轉化

    數據結構面試之二叉樹相關操作

    根據前序可知根結點為1; 根據中序可知 4 7 2 為根結點 1 的左子樹和 8 5 9 3 6 為根結點 1 的右子樹; 遞歸實現,把 4 7 2 當做新的一棵和 8 5 9 3 6 也當做新的一棵; 在遞歸的過程中輸出后序。
    發表于 10-10 14:50 ?182次閱讀
    數據結構面試之<b class='flag-5'>二叉樹</b>相關操作

    物聯網開發需要學習哪些內容?

    和需要掌握的技能。 1. 物聯網軟件開發必備編程技術: Linux C語言、數據結構 核心技能內容: 必備的Linux命令; C語言的基礎知識; C語言的數組、指針和函數; 數據結構中的線性表、棧和隊列用法及實現; 二叉樹遞歸遍歷、層次遍歷、及非
    的頭像 發表于 10-09 17:23 ?1388次閱讀