二叉樹題目:具有所有最深結點的最小子樹

文章目錄

  • 題目
    • 標題和出處
    • 難度
    • 題目描述
      • 要求
      • 示例
      • 數據范圍
  • 解法一
    • 思路和算法
    • 代碼
    • 復雜度分析
  • 解法二
    • 思路和算法
    • 代碼
    • 復雜度分析

題目

標題和出處

標題:具有所有最深結點的最小子樹

出處:865. 具有所有最深結點的最小子樹

難度

5 級

題目描述

要求

給定二叉樹的根結點 root \texttt{root} root,每個結點的深度是該結點到根的最短距離

返回包含原始樹中所有最深結點的最小子樹。

如果一個結點在整個樹的所有結點中具有最大的深度,則該結點是最深的

一個結點的子樹是該結點加上它的所有后代的集合。

示例

示例 1:

示例 1

輸入: root = [3,5,1,6,2,0,8,null,null,7,4] \texttt{root = [3,5,1,6,2,0,8,null,null,7,4]} root?=?[3,5,1,6,2,0,8,null,null,7,4]
輸出: [2,7,4] \texttt{[2,7,4]} [2,7,4]
解釋:
我們返回值為 2 \texttt{2} 2 的結點,在圖中用黃色標記。
在圖中用藍色標記的是樹的最深的結點。
注意,結點 5 \texttt{5} 5 3 \texttt{3} 3 2 \texttt{2} 2 包含樹中最深的結點,但結點 2 \texttt{2} 2 的子樹最小,因此我們返回它。

示例 2:

輸入: root = [1] \texttt{root = [1]} root?=?[1]
輸出: [1] \texttt{[1]} [1]
解釋:根結點是樹中最深的結點。

示例 3:

輸入: root = [0,1,3,null,2] \texttt{root = [0,1,3,null,2]} root?=?[0,1,3,null,2]
輸出: [2] \texttt{[2]} [2]
解釋:樹中最深的結點為 2 \texttt{2} 2,有效子樹為結點 2 \texttt{2} 2 1 \texttt{1} 1 0 \texttt{0} 0 的子樹,但結點 2 \texttt{2} 2 的子樹最小。

數據范圍

  • 樹中結點數目在范圍 [1, 500] \texttt{[1, 500]} [1,?500]
  • 0 ≤ Node.val ≤ 500 \texttt{0} \le \texttt{Node.val} \le \texttt{500} 0Node.val500
  • 樹中的所有值各不相同

解法一

思路和算法

由于所有最深結點的深度相同,因此對于包含所有最深結點的子樹,每個最深結點到子樹根結點的距離相同。只要定位到所有最深結點,即可找到包含所有最深結點的最小子樹的根結點。

為了定位到所有最深結點,可以使用層序遍歷。從根結點開始依次遍歷每一層的結點,在層序遍歷的過程中需要區分不同結點所在的層,確保每一輪訪問的結點為同一層的全部結點。遍歷每一層結點之前首先得到當前層的結點數,即可確保每一輪訪問的結點為同一層的全部結點。層序遍歷訪問的最后一層結點即為所有最深結點。

定位到所有最深結點之后,從最深結點向根結點移動,即每次從當前結點移動到父結點。由于每個最深結點到子樹根結點的距離相同,因此每個最深結點將同時移動到包含所有最深結點的最小子樹的根結點。使用哈希集合存儲每次移動之后的結點集合,每次移動之后,結點數量一定不變或減少,當只剩下一個結點時,該結點即為包含所有最深結點的最小子樹的根結點。

代碼

class Solution {public TreeNode subtreeWithAllDeepest(TreeNode root) {Map<TreeNode, TreeNode> parentMap = new HashMap<TreeNode, TreeNode>();List<TreeNode> deepest = new ArrayList<TreeNode>();Queue<TreeNode> queue = new ArrayDeque<TreeNode>();queue.offer(root);while (!queue.isEmpty()) {deepest.clear();int size = queue.size();for (int i = 0; i < size; i++) {TreeNode node = queue.poll();deepest.add(node);TreeNode left = node.left, right = node.right;if (left != null) {parentMap.put(left, node);queue.offer(left);}if (right != null) {parentMap.put(right, node);queue.offer(right);}}}Set<TreeNode> nodes = new HashSet<TreeNode>(deepest);while (nodes.size() > 1) {Set<TreeNode> parents = new HashSet<TreeNode>();for (TreeNode node : nodes) {parents.add(parentMap.get(node));}nodes = parents;}return nodes.iterator().next();}
}

復雜度分析

  • 時間復雜度: O ( n ) O(n) O(n),其中 n n n 是二叉樹的結點數。層序遍歷訪問每個結點一次,需要 O ( n ) O(n) O(n) 的時間,從所有最深結點移動到包含所有最深結點的最小子樹的根結點的時間不超過 O ( n ) O(n) O(n),因此總時間復雜度是 O ( n ) O(n) O(n)

  • 空間復雜度: O ( n ) O(n) O(n),其中 n n n 是二叉樹的結點數。空間復雜度主要是隊列空間和哈希集合,隊列內元素個數不超過 n n n,哈希集合內元素個數不超過 n n n

解法二

思路和算法

對于二叉樹中的每個結點,考慮其左子樹和右子樹的深度。如果左子樹和右子樹的深度相同,則左子樹和右子樹中都有最深結點,當前結點就是包含所有最深結點的最小子樹的根結點;如果左子樹和右子樹的深度不同,則所有最深結點一定在深度較大的子樹中,需要在深度較大的子樹中尋找包含所有最深結點的最小子樹的根結點。因此,尋找包含所有最深結點的最小子樹的根結點,等價于尋找左子樹和右子樹的深度相同的結點,以下將該結點稱為「目標結點」。

從根結點開始深度優先搜索,計算每個子樹的深度,并尋找目標結點。定義空樹的深度為 0 0 0,當子樹非空時,子樹的深度為左子樹的深度和右子樹的深度中的最大值加 1 1 1

尋找目標結點的具體做法如下。

  1. 如果當前結點的左子樹的深度和右子樹的深度相同,則當前結點即為目標結點,當前子樹的深度為左子樹的深度加 1 1 1

  2. 否則,在深度較大的子樹中尋找目標結點,當前子樹的深度為深度較大的子樹的深度加 1 1 1

上述過程是一個遞歸的過程,遞歸的終止條件是當前結點為空或者當前結點的左子樹的深度和右子樹的深度相同,其余情況則調用遞歸。

對于每個結點,首先訪問其子結點尋找目標結點和計算子樹高度,然后根據訪問子結點的結果得到當前結點的結果。計算結果的順序是先計算子結點的結果,后計算當前結點的結果,該順序實質是后序遍歷。由于在計算每個結點的結果時,該結點的子結點的結果已知,該結點的結果由子結點的結果決定,因此可以確保結果正確。

代碼

class Solution {class NodeDepth {private TreeNode node;private int depth;public NodeDepth(TreeNode node, int depth) {this.node = node;this.depth = depth;}public TreeNode getNode() {return node;}public int getDepth() {return depth;}}public TreeNode subtreeWithAllDeepest(TreeNode root) {NodeDepth rootDepth = dfs(root);return rootDepth.getNode();}public NodeDepth dfs(TreeNode node) {if (node == null) {return new NodeDepth(node, 0);}NodeDepth left = dfs(node.left), right = dfs(node.right);TreeNode leftNode = left.getNode(), rightNode = right.getNode();int leftDepth = left.getDepth(), rightDepth = right.getDepth();if (leftDepth == rightDepth) {return new NodeDepth(node, leftDepth + 1);}return leftDepth > rightDepth ? new NodeDepth(leftNode, leftDepth + 1) : new NodeDepth(rightNode, rightDepth + 1);}
}

復雜度分析

  • 時間復雜度: O ( n ) O(n) O(n),其中 n n n 是二叉樹的結點數。每個結點都被訪問一次。

  • 空間復雜度: O ( n ) O(n) O(n),其中 n n n 是二叉樹的結點數。空間復雜度主要是深度優先搜索的過程中創建實例的空間和遞歸調用的棧空間,因此空間復雜度是 O ( n ) O(n) O(n)

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

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

相關文章

HCIP-六、OSPF-2 綜合實驗

六、OSPF-2 綜合實驗 實驗拓撲實驗需求及解法1.設備名稱和部分IP地址已配置2.所有設備運行OSPF&#xff0c;進程號為13.區域間路由匯總4.外部路由匯總5.下發默認路由6. 虛鏈路 實驗拓撲 實驗需求及解法 本實驗模擬OSPF綜合型網絡&#xff0c;按照以下需求完成實驗。 1.設備名…

EventLog Analyzer:強大的日志管理與分析工具

隨著企業網絡規模的擴大和信息系統的復雜化&#xff0c;安全日志管理和分析成為了至關重要的一環。在這個背景下&#xff0c;EventLog Analyzer嶄露頭角&#xff0c;成為一款備受推崇的日志管理與分析工具。本文將介紹EventLog Analyzer的主要特點、功能以及為企業帶來的實際價…

IDEA安裝教程

文章目錄 1 下載IntelliJ IDEA2 安裝3 IDEA配置4 創建項目 1 下載IntelliJ IDEA ? 官方網站上下載最新版本的IntelliJ IDEA。官方網站提供了兩個版本&#xff1a;Community版和Ultimate版。 Community版是免費的&#xff0c;適用于個人和非商業用途。Ultimate版則需要付費購…

Exception in thread “消費者“ java.lang.IllegalMonitorStateException

這兩天學習生產者消費者模型的時候&#xff0c;使用Java線程來實現&#xff0c;出現了一個問題“Exception in thread "消費者" java.lang.IllegalMonitorStateException”&#xff0c;并且&#xff0c;線程不結束。報錯圖片如下&#xff1a; 那我們怎么解決呢&…

競賽選題 題目: 基于深度學習的疲勞駕駛檢測 深度學習

文章目錄 0 前言1 課題背景2 實現目標3 當前市面上疲勞駕駛檢測的方法4 相關數據集5 基于頭部姿態的駕駛疲勞檢測5.1 如何確定疲勞狀態5.2 算法步驟5.3 打瞌睡判斷 6 基于CNN與SVM的疲勞檢測方法6.1 網絡結構6.2 疲勞圖像分類訓練6.3 訓練結果 7 最后 0 前言 &#x1f525; 優…

河北專升本(微機原理)

目錄 第一章&#xff1a;計算機基礎與數制轉化 1. 進制運算基礎 2. 常用編碼形式 3. 計算機系統的組成及其工作原理 4. 微機系統主要技術指標 第二章&#xff1a;8086微處理器及其系統 1. 8086微處理器&#xff08;CPU&#xff09; 2. 8086的存儲器及I/O組織 3. 8086系…

vue中的列表過濾和列表排序

列表過濾 <body><div id"root"><!--輸入框用于模糊查詢--><input type"text" placeholder"請你輸入名字" v-model"name"><ul><!--in可以換成of--><li v-for"(p,index) in persons" …

航天博物館3D虛擬交互展廳讓大眾對科技發展有更深切的理解和感受

博物館作為人們了解歷史、文化和藝術的重要場所&#xff0c;現在可以通過VR全景技術來進行展覽&#xff0c;讓參觀者身臨其境地感受歷史文化的魅力。本文將介紹博物館VR全景的特點、優勢&#xff0c;以及如何使用VR全景技術來使得博物館的展覽和教育活動更豐富。 VR數字博物館…

WPF圖形變形使用技巧

在 WPF (Windows Presentation Foundation) 中&#xff0c;圖形變形通常是通過使用 Transform 對象來實現的。WPF 提供了幾種不同類型的 Transform&#xff0c;包括&#xff1a; TranslateTransform&#xff1a;用于在 x 軸和 y 軸上移動&#xff08;平移&#xff09;元素。Sc…

SSH 下載及安裝之 Windows Server

文章目錄 1 概述1.1 操作系統截圖1.2 下載 2 安裝2.1 解壓到指定路徑2.2 CMD 到 OpenSSH 目錄下2.3 安裝 sshd 服務2.3 開放端口 222.4 配置開機自啟 sshd 服務2.5 配置環境變量 path2.6 測試 3 連接3.1 使用 Xshell 連接3.2 輸入登錄用戶名3.3 輸入登錄密碼3.4 會話已建立 1 概…

3、如何從0到1去建設數據倉庫

1、數倉實施過程 1.1 數據調研 數據調研包括&#xff1a;業務調研、需求調研 業務調研 需要調研企業內有哪些業務線、業務線的業務是否還有相同點和差異點 各個業務線有哪些業務模塊&#xff0c;每個模型下有哪些業務流程&#xff0c;每個流程下產生的數據 是怎樣存儲的 業務調…

python數據結構與算法-16_優先級隊列

優先級隊列 你可能比較奇怪&#xff0c;隊列不是早就講了嘛。這里之所以放到這里講優先級隊列&#xff0c;是因為雖然名字有隊列&#xff0c; 但其實是使用堆來實現的。上一章講完了堆&#xff0c;這一章我們就趁熱打鐵來實現一個優先級隊列。 實現優先級隊列 優先級隊列(Pr…

UWA報告使用技巧小視頻,你get了么?(第十一彈)

隨著玩家對手游渲染品質的要求日益趨上&#xff0c;60幀、各種花式后處理導致發熱、耗電等問題日趨明顯。本期UWA報告使用技巧將分享關于GPU優化的專題姊妹篇。 《GPU性能優化篇》 UWA專注于手游GPU性能的優化&#xff0c;以確保您的游戲體驗得以最佳展現。基于最新發布的GOT …

141.【Git版本控制】

Git-深入挖掘 (一)、Git分布式版本控制工具1.目標2.概述(1).開發中的實際常見(2).版本控制器的方式(3).SVN (集中版本控制器)(4).Git (分布版本控制器)(5).Git工作流程圖 (二)、Git安裝與常用命令1.Git環境配置(1).安裝Git的操作(2).Git的配置操作(3).為常用的指令配置別名 (可…

輕松解決rpm軟件包的依賴問題 yum download ,rpm和deb不同系列

centos rpm系列的 為它往往有很多依賴項目。比如&#xff0c;我們來查看一下net-tools的依賴項有哪些&#xff1a; yum deplist net-tools 推薦使用以下幾種方法&#xff1a; 1.repotrack 我這里也以上期講到的Mariadb為例演示&#xff0c;以下操作需要在有網絡的環境下進…

國內企業出海首選的免費開源訂單管理系統(OMS)解決方案

用開源智造Odoo訂單管理系統 (OMS) 解決方案實現"訂單到收款"流程自動化 開源智造Odoo 訂單管理軟件功能消除了手動操作瓶頸&#xff0c;可防止出錯&#xff0c;還建立了從銷售報價到訂單履行的順暢工作流來確保及時開票和付款&#xff0c;從而幫助您理順訂單處理過程…

Python將多個視頻幀組合成.mp4視頻

已經有很多文章描述了如何將視頻拆分成視頻幀&#xff0c;例如&#xff1a;https://blog.csdn.net/WYKB_Mr_Q/article/details/124929081 那我們如何將很多視頻幀重新組合成視頻呢&#xff1f; 這里我們主要用到了 OpenCV 庫中的 VideoWriter 類。 OpenCV種的 cv2.VideoWrit…

jdbc批量插入或更新數據

mybatis可以批量插入或更新數據&#xff0c;不過mybatis底層也是基于jdbc來實現的&#xff0c;如何使用jdbc批量操作數據&#xff1f;本文給出demo。 /*** JDBC分批次批量插入* * throws IOException*/public static void testJDBCBatchInsertUser() throws IOException {Conne…

工作流引擎的架構設計主要考慮以下方面

工作流引擎的架構設計主要考慮以下方面&#xff0c;以馳騁工作流引擎為例來說明。 高度抽象和封裝&#xff1a;為了適應各種業務場景&#xff0c;工作流引擎應具備高度抽象和封裝的特性&#xff0c;以便統一處理各流程。靈活配置&#xff1a;工作流引擎應支持靈活的配置&#…

Linux之實現簡易的shell

1.打印提示符并獲取命令行 我們在使用shell的時候&#xff0c;發現我們在輸入命令是&#xff0c;前面會有&#xff1a;有用戶名&#xff0c;版本&#xff0c;當前路徑等信息&#xff0c;這里我們可以用環境變量去獲取: 1 #include <stdio.h>2 #include <stdlib.h>…