熱門面試題第13天|Leetcode 110.平衡二叉樹 257. 二叉樹的所有路徑 404.左葉子之和 222.完全二叉樹的節點個數

222.完全二叉樹的節點個數(優先掌握遞歸)

需要了解,普通二叉樹 怎么求,完全二叉樹又怎么求

題目鏈接/文章講解/視頻講解:https://programmercarl.com/0222.%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%8A%82%E7%82%B9%E4%B8%AA%E6%95%B0.html

首先按照普通二叉樹的邏輯來求。

這道題目的遞歸法和求二叉樹的深度寫法類似, 而迭代法,二叉樹:層序遍歷登場!?(opens new window)遍歷模板稍稍修改一下,記錄遍歷的節點數量就可以了。

遞歸遍歷的順序依然是后序(左右中)。

完全二叉樹只有兩種情況,情況一:就是滿二叉樹,情況二:最后一層葉子節點沒有滿。

對于情況一,可以直接用 2^樹深度 - 1 來計算,注意這里根節點深度為1。

對于情況二,分別遞歸左孩子,和右孩子,遞歸到某一深度一定會有左孩子或者右孩子為滿二叉樹,然后依然可以按照情況1來計算。

?對于情況二,如果一開始沒有找到滿二叉樹,就會去+1,然后從左右節點再去找二叉樹,這樣子遞歸,所以不用擔心會漏節點。我們來看兩種方法的代碼

class Solution {// 通用遞歸解法public int countNodes(TreeNode root) {if(root == null) {return 0;}return countNodes(root.left) + countNodes(root.right) + 1;}
}
class Solution {/*** 針對完全二叉樹的解法** 滿二叉樹的結點數為:2^depth - 1*/public int countNodes(TreeNode root) {if (root == null) return 0;TreeNode left = root.left;TreeNode right = root.right;int leftDepth = 0, rightDepth = 0; // 這里初始為0是有目的的,為了下面求指數方便while (left != null) {  // 求左子樹深度left = left.left;leftDepth++;}while (right != null) { // 求右子樹深度right = right.right;rightDepth++;}if (leftDepth == rightDepth) {return (2 << leftDepth) - 1; // 注意(2<<1) 相當于2^2,所以leftDepth初始為0}return countNodes(root.left) + countNodes(root.right) + 1;}
}

110.平衡二叉樹 (優先掌握遞歸)

再一次涉及到,什么是高度,什么是深度,可以鞏固一下。

題目鏈接/文章講解/視頻講解:https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91.html

此時大家應該明白了既然要求比較高度,必然是要后序遍歷。

遞歸三步曲分析:

  1. 明確遞歸函數的參數和返回值

參數:當前傳入節點。 返回值:以當前傳入節點為根節點的樹的高度。

那么如何標記左右子樹是否差值大于1呢?

如果當前傳入節點為根節點的二叉樹已經不是二叉平衡樹了,還返回高度的話就沒有意義了。

所以如果已經不是二叉平衡樹了,可以返回-1 來標記已經不符合平衡樹的規則了。

private int getHeight(TreeNode root)

2.明確終止條件

遞歸的過程中依然是遇到空節點了為終止,返回0,表示當前節點為根節點的樹高度為0

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

3.明確單層遞歸的邏輯

如何判斷以當前傳入節點為根節點的二叉樹是否是平衡二叉樹呢?當然是其左子樹高度和其右子樹高度的差值。

分別求出其左右子樹的高度,然后如果差值小于等于1,則返回當前二叉樹的高度,否則返回-1,表示已經不是二叉平衡樹了。

我們來看完整代碼

class Solution {/*** 遞歸法*/public boolean isBalanced(TreeNode root) {return getHeight(root) != -1;}private int getHeight(TreeNode root) {if (root == null) {return 0;}int leftHeight = getHeight(root.left);if (leftHeight == -1) {return -1;}int rightHeight = getHeight(root.right);if (rightHeight == -1) {return -1;}// 左右子樹高度差大于1,return -1表示已經不是平衡樹了if (Math.abs(leftHeight - rightHeight) > 1) {return -1;}return Math.max(leftHeight, rightHeight) + 1;}
}

257. 二叉樹的所有路徑 (優先掌握遞歸)

這是大家第一次接觸到回溯的過程, 我在視頻里重點講解了 本題為什么要有回溯,已經回溯的過程。

如果對回溯 似懂非懂,沒關系, 可以先有個印象。

題目鏈接/文章講解/視頻講解:https://programmercarl.com/0257.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%89%80%E6%9C%89%E8%B7%AF%E5%BE%84.html

這道題目要求從根節點到葉子的路徑,所以需要前序遍歷,這樣才方便讓父節點指向孩子節點,找到對應的路徑。

在這道題目中將第一次涉及到回溯,因為我們要把路徑記錄下來,需要回溯來回退一個路徑再進入另一個路徑。

前序遍歷以及回溯的過程如圖:

?1.遞歸函數參數以及返回值

我們需要傳入一個根節點root,記錄每一條路徑path,和存放結果集的result,這里遞歸不需要返回值

private void traversal(TreeNode root, List<Integer> paths, List<String> res)

2.確定終止條件

我們找到了一個葉子節點,也就結束這一次遞歸

if (cur->left == NULL && cur->right == NULL) {終止處理邏輯
}

我們再來看一下終止邏輯

// 輸出StringBuilder sb = new StringBuilder();// StringBuilder用來拼接字符串,速度更快for (int i = 0; i < paths.size() - 1; i++) {sb.append(paths.get(i)).append("->");}sb.append(paths.get(paths.size() - 1));// 記錄最后一個節點res.add(sb.toString());// 收集一個路徑return;

我們用StringBuilder來拼接字符串,然后我們開始循環遍歷path將其存入sb中,注意不要遍歷到最后一個元素,因為題目要求“->”,所以我們遍歷到倒數第二個元素即可,然后將再單獨添加卒子后一個元素,最后將拼接的sb添加給res,然后結束方法

3.確定單層遞歸邏輯

因為這道題是前序遍歷,我們需要先處理中間節點,中間節點就是我們要記錄的路徑上的節點,先放進path中

path.push_back(cur->val);

然后進行左右的遞歸回溯,為什么我們需要將判斷葉子節點放在遍歷之前,因為如果是葉子節點,我們直接退出,然后進行返回結果。

我們來看代碼

/方式一
class Solution {/*** 遞歸法*/public List<String> binaryTreePaths(TreeNode root) {List<String> res = new ArrayList<>();// 存最終的結果if (root == null) {return res;}List<Integer> paths = new ArrayList<>();// 作為結果中的路徑traversal(root, paths, res);return res;}private void traversal(TreeNode root, List<Integer> paths, List<String> res) {paths.add(root.val);// 前序遍歷,中// 遇到葉子結點if (root.left == null && root.right == null) {// 輸出StringBuilder sb = new StringBuilder();// StringBuilder用來拼接字符串,速度更快for (int i = 0; i < paths.size() - 1; i++) {sb.append(paths.get(i)).append("->");}sb.append(paths.get(paths.size() - 1));// 記錄最后一個節點res.add(sb.toString());// 收集一個路徑return;}// 遞歸和回溯是同時進行,所以要放在同一個花括號里if (root.left != null) { // 左traversal(root.left, paths, res);paths.remove(paths.size() - 1);// 回溯}if (root.right != null) { // 右traversal(root.right, paths, res);paths.remove(paths.size() - 1);// 回溯}}

404.左葉子之和 (優先掌握遞歸)

其實本題有點文字游戲,搞清楚什么是左葉子,剩下的就是二叉樹的基本操作。

題目鏈接/文章講解/視頻講解:https://programmercarl.com/0404.%E5%B7%A6%E5%8F%B6%E5%AD%90%E4%B9%8B%E5%92%8C.html

首先要注意是判斷左葉子,不是二叉樹左側節點,所以不要上來想著層序遍歷。

因為題目中其實沒有說清楚左葉子究竟是什么節點,那么我來給出左葉子的明確定義:節點A的左孩子不為空,且左孩子的左右孩子都為空(說明是葉子節點),那么A節點的左孩子為左葉子節點

如果該節點的左節點不為空,該節點的左節點的左節點為空,該節點的左節點的右節點為空,則找到了一個左葉子,判斷代碼如下:?

if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) {左葉子節點處理邏輯
}

1.確定終止條件

如果遍歷到空節點,那么左葉子值一定是0,只有當前遍歷的節點是父節點,才能判斷其子節點是不是左葉子。 所以如果當前遍歷的節點是葉子節點,那其左葉子也必定是0,那么終止條件為:

if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0; //其實這個也可以不寫,如果不寫不影響結果,但就會讓遞歸多進行了一層

?2.確定單層遞歸的邏輯

當遇到左葉子節點的時候,記錄數值,然后通過遞歸求取左子樹左葉子之和,和 右子樹左葉子之和,相加便是整個樹的左葉子之和。

int leftValue = sumOfLeftLeaves(root.left);    // 左if (root.left != null && root.left.left == null && root.left.right == null) { // 左子樹就是一個左葉子的情況leftValue = root.left.val;}int rightValue = sumOfLeftLeaves(root.right);  // 右int sum = leftValue + rightValue;              // 中return sum;

我們來看完整代碼

class Solution {public int sumOfLeftLeaves(TreeNode root) {if (root == null) return 0;if (root.left == null && root.right == null) return 0;int leftValue = sumOfLeftLeaves(root.left);    // 左if (root.left != null && root.left.left == null && root.left.right == null) { // 左子樹就是一個左葉子的情況leftValue = root.left.val;}int rightValue = sumOfLeftLeaves(root.right);  // 右int sum = leftValue + rightValue;              // 中return sum;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75561.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75561.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75561.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于Object.assign

Object.assign 基本用法 Object.assign() 方法用于將所有可枚舉屬性的值從一個或者多個源對象source復制到目標對象。它將返回目標對象target const target { a: 1, b: 2 } const source { b: 4, c: 5 }const returnedTarget Object.assign(target, source)target // { a…

GitHub高級篩選小白使用手冊

GitHub高級篩選小白使用手冊 GitHub 提供了強大的搜索功能&#xff0c;允許用戶通過高級篩選器來精確查找倉庫、Issues、Pull Requests、代碼等。下面是一些常用的高級篩選用法&#xff0c;幫助你更高效地使用 GitHub 搜索功能。 目錄 搜索倉庫搜索Issues搜索Pull Requests搜…

手動集成sqlite的方法

注意到sqlite有backup方法&#xff08;https://www.sqlite.org/backup.html&#xff09;。 也注意到android中sysroot下&#xff0c;沒有sqlite3的庫&#xff0c;也沒有相關頭文件。 如果要使用 sqlite 的backup&#xff0c;那么就需要手動集成sqlite代碼到項目中。可以如下操…

藍橋杯真題 2109.統計子矩陣

原題地址:1.統計子矩陣 - 藍橋云課 問題描述 給定一個 NMNM 的矩陣 AA, 請你統計有多少個子矩陣 (最小 1111, 最大 NM)NM) 滿足子矩陣中所有數的和不超過給定的整數 KK ? 輸入格式 第一行包含三個整數 N,MN,M 和 KK. 之后 NN 行每行包含 MM 個整數, 代表矩陣 AA. 輸出格…

藍橋杯—最少操作數

一.題目 分析:每次可以進行三次操作&#xff0c;求在n步操作后可以達到目標數的最小n&#xff0c;和最短路徑問題相似&#xff0c;分層遍歷加記憶化搜索防止時間復雜度過高&#xff0c;還需要減枝操作 import java.util.HashSet; import java.util.LinkedList; import java.ut…

Linux內核NIC網卡驅動實戰案例分析

以下Linux 內核模塊實現了一個虛擬網絡設備驅動程序&#xff0c;其作用和意義如下&#xff1a; 1. 作用 &#xff08;1&#xff09;創建虛擬網絡設備對 驅動程序動態創建了兩個虛擬網絡設備&#xff08;nic_dev[0]和nic_dev[1]&#xff09;&#xff0c;模擬物理網卡的功能。這兩…

Trae初使用心得(Java后端)

1.前提 2025年3月3日&#xff0c;字節跳動正式官宣“中國首個 AI 原生集成開發環境&#xff08;AI IDE&#xff09;”Trae 國內版正式上線&#xff0c;由于之前項目的原因小編沒有及時的去體驗&#xff0c;這幾日專門抽空去體驗了一下感覺還算可以。 2.特點 Trade重在可以白嫖…

[項目]基于FreeRTOS的STM32四軸飛行器: 十二.角速度加速度濾波

基于FreeRTOS的STM32四軸飛行器: 十二.濾波 一.濾波介紹二.對角速度進行一階低通濾波三.對加速度進行卡爾曼濾波 一.濾波介紹 模擬信號濾波&#xff1a; 最常用的濾波方法可以在信號和地之間并聯一個電容&#xff0c;因為電容通交隔直&#xff0c;信號突變會給電容充電&#x…

UNIX網絡編程筆記:TCP、UDP、SCTP編程的區別

一、核心特性對比 特性TCPUDPSCTP連接方式面向連接&#xff08;三次握手&#xff09;無連接面向連接&#xff08;四次握手&#xff09;可靠性可靠傳輸&#xff08;重傳、確認機制&#xff09;不可靠傳輸可靠傳輸&#xff08;多路徑冗余&#xff09;傳輸單位字節流&#xff08;…

Python爬蟲異常處理:自動跳過無效URL

爬蟲在運行過程中常常會遇到各種異常情況&#xff0c;其中無效URL的出現是較為常見的問題之一。無效URL可能導致爬蟲程序崩潰或陷入無限等待狀態&#xff0c;嚴重影響爬蟲的穩定性和效率。因此&#xff0c;掌握如何在Python爬蟲中自動跳過無效URL的異常處理技巧&#xff0c;對于…

C++語法學習的主要內容

科技特長生方向&#xff0c;主要學習的內容為 一&#xff0c;《C語法》 二&#xff0c;《數據結構》 三&#xff0c;《算法》 四&#xff0c;《計算機基礎知識》 五&#xff0c;《初高中的數學知識》 其中&#xff0c;《C語法》學習的主要內容如下: 1,cout輸出語句和鍵盤…

3、孿生網絡/連體網絡(Siamese Network)

目的: 用Siamese Network (孿生網絡) 解決Few-shot learning (小樣本學習)。 Siamese Network并不是Meta Learning最好的方法, 但是通過學習Siamese Network,非常有助于理解其他Meta Learning算法。 這里介紹了兩種方法:Siamese Network (孿生網絡)、Trplet Loss Siam…

從零構建大語言模型全棧開發指南:第二部分:模型架構設計與實現-2.2.1從零編寫類GPT-2模型架構(規劃模塊與代碼組織)

?? 點擊關注不迷路 ?? 點擊關注不迷路 ?? 點擊關注不迷路 文章大綱 2.2.1 從零編寫類GPT-2模型架構(規劃模塊與代碼組織)1. 模型架構設計規劃1.1 架構核心組件2. 模塊化設計實現2.1 輸入處理模塊2.1.1 分詞與嵌入2.1.2 位置編碼2.2 解碼塊設計2.2.1 多頭注意力子層2.2.…

消息隊列(Kafka及RocketMQ等對比聯系)

目錄 消息隊列 一、為什么使用消息隊列&#xff1f;消息隊列有什么優點/缺點&#xff1f;介紹下Kafka、ActiveMQ、RabbitMQ、RocketMQ有什么優點缺點&#xff0c;如何取舍&#xff1f; 1.公司業務場景是什么&#xff0c;這個業務場景有什么挑戰&#xff0c;如果不用MQ有什么麻…

Android 13系統定制實戰:基于系統屬性的音量鍵動態屏蔽方案解析

1. 需求背景與實現原理 在Android 13系統定制化開發中&#xff0c;需根據設備場景動態屏蔽音量鍵&#xff08;VOLUME_UP/VOLUME_DOWN&#xff09;功能。其核心訴求是通過系統屬性&#xff08;persist.sys.roco.volumekey.enable&#xff09;控制音量鍵的響應邏輯&#xff0c;確…

解鎖DeepSeek潛能:Docker+Ollama打造本地大模型部署新范式

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、什么是Docker 2、什么是Ollama 二、準備工作 1、操…

uv - Guides 指南 [官方文檔翻譯]

文章目錄 Guides 指南概述安裝 Python入門安裝特定版本重新安裝 Python查看 Python 安裝自動 Python 下載使用現有的 Python 版本 運行腳本在沒有依賴的情況下運行腳本運行帶有依賴的腳本創建一個Python腳本聲明腳本依賴使用替代包索引鎖定依賴提高可重復性使用不同的 Python 版…

根據模板將 Excel 明細數據生成 PDF 文檔 | PDF實現郵件合并功能

在日常辦公中&#xff0c;我們常常會面臨這樣的需求&#xff1a;依據特定的模板&#xff0c;把 Excel 里的每一條數據轉化為單獨的 PDF 文檔&#xff0c;且這些 PDF 文檔中的部分內容會根據 Excel 數據動態變化。這一功能不僅能高效完成任務&#xff0c;還支持圖片的動態替換&a…

apache安裝腳本使用shell建立

注意防火墻&#xff0c;yum&#xff0c;網絡連接等 以下是具體的apache安裝腳本 #!/bin/bash # Set Apache version to install ## author: yuan # 檢查外網連接 echo "檢查外網連接..." ping www.baidu.com -c 3 > /dev/null 2>&1 if [ $? -eq 0 ]; …

wordpress主題使用中常見錯誤匯總

在WordPress主題的使用過程中&#xff0c;開發者可能會遇到各種問題。下面是一些常見錯誤的匯總&#xff0c;并給出了相應的解決方法。 一、主題安裝與激活錯誤 無法激活主題&#xff1a;檢查主題文件是否完整&#xff0c;以及是否符合WordPress的主題規范。 激活主題后出現…