【算法訓練營Day14】二叉樹part4

文章目錄

  • 找樹左下角的值
  • 路徑總和
  • 總結:遞歸函數的返回值
  • 路徑總和 II
  • 總結:二叉樹遞歸的思考
  • 從中序與后序遍歷序列構造二叉樹

找樹左下角的值

題目鏈接:513. 找樹左下角的值

解題邏輯:

使用層序遍歷,將最后一層的第一個元素拿出來即可。

class Solution {public int findBottomLeftValue(TreeNode root) {Deque<List<Integer>> allItem = new LinkedList<>();Deque<TreeNode> que = new ArrayDeque<>();que.add(root);while(!que.isEmpty()) {List<Integer> row = new ArrayList<>();int count = que.size();while(count > 0) {TreeNode node = que.remove();count--;row.add(node.val);if(node.left != null) que.add(node.left);if(node.right != null) que.add(node.right);}allItem.add(row);}return allItem.removeLast().get(0);}
}

路徑總和

題目鏈接:112. 路徑總和

解題邏輯:

這個題可以當作257. 二叉樹的所有路徑這道題的延深,我們可以沿用此題的代碼,最后遍歷每條路徑上的和是否有符合條件的即可。

class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {if(root == null) return false;Deque<Integer> path = new ArrayDeque<>();List<Integer> allPathsAdd = new ArrayList<>();getAllPath(root,path,allPathsAdd);for(Integer sum : allPathsAdd) if(targetSum == sum) return true;return false;}public void getAllPath(TreeNode node,Deque<Integer> path,List<Integer> allPathsAdd){path.add(node.val);if(node.left == null && node.right == null) {int add =  0;for(Integer num : path) add += num;allPathsAdd.add(add);}if(node.left != null) {getAllPath(node.left,path,allPathsAdd);path.removeLast();}if(node.right != null) {getAllPath(node.right,path,allPathsAdd);path.removeLast();}}
}

上面的代碼是在257代碼的基礎上修改而來,這樣其實效率并不是很高,因為我們相當于是把所有路徑遍歷了出來,然后再檢驗是否存在符合條件的路徑,但其實我們在遍歷的途中發現有一條路徑已經符合條件了,那么就可以直接返回了,這樣就大大提升了效率。

修改后的代碼如下:

class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {if(root == null) return false;int count = 0;return getPathSum(root,count,targetSum);}public boolean getPathSum(TreeNode node,int count,int targetSum){count += node.val;if(node.left == null && node.right == null) {if(count == targetSum) return true;return false;}if(node.left != null) {boolean left = getPathSum(node.left,count,targetSum);if(left == true) return true;}if(node.right != null) {boolean right = getPathSum(node.right,count,targetSum);if(right == true) return true;}return false;}
}

總結:遞歸函數的返回值

遞歸函數什么時候需要返回值?什么時候不需要返回值?這里總結如下三點:

  • 如果需要搜索整棵二叉樹且不用處理遞歸返回值,遞歸函數就不要返回值。(這種情況就是本文下半部分介紹的113.路徑總和ii)
  • 如果需要搜索整棵二叉樹且需要處理遞歸返回值,遞歸函數就需要返回值。 (這種情況我們在236. 二叉樹的最近公共祖先 (opens new window)中介紹)
  • 如果要搜索其中一條符合條件的路徑,那么遞歸一定需要返回值,因為遇到符合條件的路徑了就要及時返回。(本題的情況)

路徑總和 II

題目鏈接:113. 路徑總和 II

與上一題的區別在于,本題要尋找所有符合條件的路徑,所以要遍歷整棵樹,并且我們對遞歸的返回值也不做處理,所以我們的遞歸方法可以不設置返回值。

代碼如下:

class Solution {public List<List<Integer>> pathSum(TreeNode root, int targetSum) {if(root == null) return new ArrayList<List<Integer>>();List<Integer> path = new ArrayList<>();List<List<Integer>> result = new ArrayList<>();getPathSum(root,path,targetSum,result);return result;}public void getPathSum(TreeNode node,List<Integer> path,int targetSum,List<List<Integer>> result){path.add(node.val);if(node.left == null && node.right == null) {int count = 0;for(Integer num : path) count += num;if(count == targetSum) {List<Integer> deepCopy = new ArrayList<>();for (Integer obj : path) {deepCopy.add(obj); }result.add(deepCopy);   } return;}if(node.left != null) {getPathSum(node.left,path,targetSum,result);path.remove(path.size() - 1);}if(node.right != null) {getPathSum(node.right,path,targetSum,result);path.remove(path.size() - 1);}}
}

總結:二叉樹遞歸的思考

在這里插入圖片描述

遍歷的選擇:看中的邏輯中需不需要左右的參與

遞歸,是遞和歸的兩個過程:

  • 參數是在遞的過程中層層深入
  • 返回值是在歸的過程中逐層向上返回
  • 而回溯算法的邏輯就在歸的過程之后

從中序與后序遍歷序列構造二叉樹

題目鏈接:106. 從中序與后序遍歷序列構造二叉樹

解題邏輯:

首先要了解想要恢復一顆二叉樹,那么一定需要兩種遍歷方法,其中中序遍歷是一定需要的,而另一種遍歷方式可以是前序、后序、層序遍歷方式。

復原的原理如下圖所示:

在這里插入圖片描述

本題是考察通過中序和后序構造二叉樹,其中后序遍歷是用來確定根節點的,而中序是用來確定根節點的左右子樹情況的。

本題選用后序遍歷的遞歸方式,這樣最后可以將左右子樹的根節點拼接到二叉樹的根節點左右。接下來從遞歸三部曲開始分析:

  • 遞歸的參數與返回值:返回值為TreeNode,而參數為前序列表與后序列表,接下來將會對他遞歸切割
  • 遞歸出口:當后序列表長度為0的時候,直接返回null。當后序列表的長度為1的時候,則直接根據這個值構建節點返回
  • 遞歸單層邏輯:
    • 取到后序列表的最后一個元素,作為當前遞歸根節點
    • 在中序列表中找到該元素
    • 根據該元素對中序列表、后序列表進行切割
    • 左遞歸獲得左子節點
    • 右遞歸獲得右子節點
    • 將左右子節點組裝到根節點上
    • 返回根節點

代碼如下:

class Solution {public TreeNode buildTree(int[] inorder, int[] postorder) {if(postorder.length == 0) return null;if(postorder.length == 1) return new TreeNode(postorder[0]);int devideNum = postorder[postorder.length - 1];TreeNode root = new TreeNode(devideNum);int[] inorderLeft = Arrays.copyOfRange(inorder, 0, findNum(inorder,devideNum));int[] postorderLeft = Arrays.copyOfRange(postorder, 0, inorderLeft.length);root.left = buildTree(inorderLeft,postorderLeft);int[] inorderRight;if(findNum(inorder,devideNum) == inorder.length - 1) {inorderRight = new int[0];}else {inorderRight = Arrays.copyOfRange(inorder, findNum(inorder,devideNum) + 1,inorder.length);}int[] postorderRight = Arrays.copyOfRange(postorder, postorderLeft.length, postorder.length - 1);root.right = buildTree(inorderRight,postorderRight);return root;}public int findNum(int[] nums,int target){for(int i = 0;i < nums.length;i++) {if(nums[i] == target) return i;}return -1;}
}

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

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

相關文章

工資系統如何計算工資

工資系統計算工資是一個集成數據收集、規則應用、自動核算和合規審核的自動化過程&#xff0c;以下是其核心原理和步驟&#xff0c;結合技術實現與法規要求進行說明&#xff1a;?? 一、工資系統的基本框架與數據準備系統初始化與規則配置企業信息設置&#xff1a;錄入公司名稱…

車載通信架構 --- DoIP協議通信

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 鈍感力的“鈍”,不是木訥、遲鈍,而是直面困境的韌勁和耐力,是面對外界噪音的通透淡然。 生活中有兩種人,一種人格外在意別人的眼光;另一種人無論…

基于Event Sourcing和CQRS的微服務架構設計與實戰

基于Event Sourcing和CQRS的微服務架構設計與實戰 業務場景描述 在電商系統中&#xff0c;訂單的高并發寫入與復雜的狀態流轉&#xff08;下單、支付、發貨、退貨等&#xff09;給傳統的CRUD模型帶來了挑戰&#xff1a; 數據一致性難保證&#xff1a;跨服務事務處理復雜&#x…

初級安全課第二次作業

&#xff08;一&#xff09;xss-labs 1~8關 1、前期準備 &#xff08;1&#xff09;打開小皮面板&#xff0c;并啟動Apache和MySQL&#xff08;2&#xff09;將 xss-labs放到 phpstudy_pro 的 WWW 目錄下&#xff08;3&#xff09;訪問連接&#xff1a;http://localhost/xss-la…

從零搭建智能搜索代理:LangGraph + 實時搜索 + PDF導出完整項目實戰

傳統的AI聊天系統往往局限于預訓練數據的知識范圍&#xff0c;無法獲取實時信息。本文將詳細闡述如何構建一個基于LangGraph的智能代理系統&#xff0c;該系統能夠智能判斷何時需要進行網絡搜索、有效維護對話上下文&#xff0c;并具備將對話內容導出為PDF文檔的功能。 本系統…

C語言分支和循環語句——猜數字游戲

分支語句的語法形式1. if(表達式)語句;2. if(表達式)語句1;else語句2;3. Switch(表達式){ case 1: break;case 2: break;case 3: break; default: break; }循環語句的語法形式1. while(表達式)語句 ;2. for&#xff08;表達…

Python設計模式深度解析:原型模式(Prototype Pattern)完全指南

Python設計模式深度解析&#xff1a;原型模式&#xff08;Prototype Pattern&#xff09;完全指南前言什么是原型模式&#xff1f;模式的核心組成實際案例&#xff1a;游泳比賽管理系統游泳者數據結構原型模式的實現深拷貝 vs 淺拷貝&#xff1a;核心概念解析淺拷貝&#xff08…

SAP-ABAP:SAP萬能長度計算:DYNAMIC_OUTPUT_LENGTH 深度解析

&#x1f4cf; SAP ABAP 萬能長度計算&#xff1a;DYNAMIC_OUTPUT_LENGTH 深度解析核心作用&#xff1a;智能計算數據對象在列表/ALV中的實際顯示寬度 | 關鍵優勢&#xff1a;多字節字符處理 | 格式感知 | 動態適配&#x1f50d; 一、核心功能與技術特性 &#x1f4ca; 數據類型…

20250720-2-Kubernetes 調度-資源限制對Pod調度的影響(1)_筆記

一、創建一個Pod的工作流程&#xfeff;1. k8s架構解析&#xfeff;組件交互模式: Kubernetes采用list-watch機制的控制器架構&#xff0c;實現組件間交互的解耦。各組件通過監控自己負責的資源&#xff0c;當資源發生變化時由kube-apiserver通知相關組件。類比說明: 類似小賣鋪…

mobaxteam x11傳輸界面避坑

mobaxteam x11傳輸界面避坑 文章目錄mobaxteam x11傳輸界面避坑1 windows系統必須下載xing2 配置1 windows系統必須下載xing 因為windows系統本身沒有x服務。 2 配置 如圖

flink sql如何對hive string類型的時間戳進行排序

在 Flink SQL 中對 Hive 表的 STRING 類型時間戳進行排序&#xff0c;需要先將字符串轉換為時間類型&#xff0c;再基于時間類型排序。以下是具體方法和示例&#xff1a; 一、核心解決方案 1. 字符串轉 TIMESTAMP 后排序 若 Hive 中的時間戳格式為 yyyy-MM-dd HH:mm:ss&#xf…

Linux:線程控制

線程概念線程&#xff08;Thread&#xff09;是進程&#xff08;Process&#xff09; 中的一個執行單元&#xff0c;是操作系統能夠進行運算調度的最小單位。線程也被稱為“輕量級進程”&#xff08;Lightweight Process, LWP&#xff09;。一個進程可以包含多個線程&#xff0…

React 學習(4)

核心API———createRoot、render方法1.createRoot 方法是創建react的根容器&#xff0c;就是react元素的插入位置&#xff0c;插入的dom會被轉化成react元素&#xff0c;根容器內的內容都會被react管理&#xff0c;原有dom都會被刪除。react17 根容器創建、渲染方式&#xff0…

ASP .NET Core 8集成Swagger全攻略

Swagger (現在稱為 OpenAPI) 是一個用于描述 RESTful API 的規范&#xff0c;ASP.NET Core 內置支持通過 Swashbuckle 庫生成 Swagger 文檔。以下是在 ASP.NET Core 8 中實現 Swagger 的完整步驟。1、添加Swagger NuGet 包dotnet add package Swashbuckle.AspNetCore2、添加Swa…

【iOS】源碼閱讀(六)——方法交換

文章目錄方法交換什么是Method-Swizzling方法交換核心API**1. 獲取方法對象****2. 添加/替換方法實現****3. 交換方法實現****4. 獲取方法信息****5. 修改方法實現****使用示例&#xff1a;完整的 Method-Swizzling 流程****注意事項**使用方法交換注意事項線程安全方法交換的影…

mysql運維問題解決:MySQL主從延遲(鎖阻塞與讀寫分離)

小亦平臺會持續給大家科普一些運維過程中常見的問題解決案例&#xff0c;運維朋友們可以在常見問題及解決方案專欄查看更多案例 問題概述 告警事件&#xff1a; 2023-07-28 03:31:39.571 首次觸發主從延遲告警&#xff08;延遲1515秒&#xff09;2023-07-28 07:41:37 告警解除…

SSH 密鑰

什么是 SSH 密鑰 SSH 密鑰就像是你電腦的“身份證”和“鑰匙”&#xff0c; 用來安全登錄另一臺電腦&#xff08;服務器&#xff09;&#xff0c;而不需要每次輸入密碼。SSH 密鑰是一種安全登錄遠程服務器的方式&#xff0c;由一對加密的“鑰匙”組成&#xff1a;一個公鑰 一個…

st-Gcn訓練跳繩識別模型一:數據標注工具和標注流程

目錄 工具展示和使用說明 工具標注后文件展示說明 json轉換成單個npy文件 數據獲取補充 工具展示和使用說明 文件名labelV.py集于PySide6實現&#xff1a; 通過選擇視頻來選擇你要標注的視頻&#xff0c;然后選擇保存路徑&#xff1a; 然后視頻兩個類別。當你看見視頻中的人…

springboot跨域問題 和 401

springboot跨域問題 和 401 1.跨域import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

構建直播平臺大體的流程

? 直播流程完整鏈路&#xff08;基于 SRS OBS 前后端&#xff09;&#x1f9cd;?♂? 用戶操作流程&#xff1a;? 用戶登錄系統&#xff08;前端&#xff09;系統中校驗用戶身份&#xff08;JWT 等&#xff09;后端可能校驗權限&#xff0c;比如“是否有開播資格”? 用戶…