代碼隨想錄學習摘抄day7(二叉樹11-21)

一個樸實無華的目錄

  • 題型
    • 226.翻轉二叉樹
      • 思路:把每一個節點的左右孩子交換一下
    • 101. 對稱二叉樹
      • 思路:使用隊列來比較兩個樹(根節點的左右子樹)是否相互翻轉
    • 222.完全二叉樹的節點個數
      • 思路:本題直接就是求有多少個節點,無腦存進結果變量就行了。
    • 110.平衡二叉樹
      • 思路:比較高度,必然是要后序遍歷。
    • 257. 二叉樹的所有路徑
      • 思路:把路徑記錄下來,需要回溯來回退一個路徑再進入另一個路徑。
        • 遞歸三部曲
          • 1.遞歸函數參數以及返回值
          • 2.確定遞歸終止條件
          • 3.確定單層遞歸邏輯
    • 404.左葉子之和
      • 思路:如果該節點的左節點不為空,該節點的左節點的左節點為空,該節點的左節點的右節點為空,則找到了一個左葉子
    • 513.找樹左下角的值
      • 思路:
    • 112. 路徑總和
      • 思路:
    • 106.從中序與后序遍歷序列構造二叉樹
      • 思路:
    • 654.最大二叉樹
      • 思路:構造樹一般采用的是前序遍歷,因為先構造中間節點,然后遞歸構造左子樹和右子樹。

題型

226.翻轉二叉樹

思路:把每一個節點的左右孩子交換一下

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;}
};

101. 對稱二叉樹

給定一個二叉樹,檢查它是否是鏡像對稱的。

思路:使用隊列來比較兩個樹(根節點的左右子樹)是否相互翻轉

class Solution {
public:bool isSymmetric(TreeNode* root) {if (root == NULL) return true;queue<TreeNode*> que;que.push(root->left);   // 將左子樹頭結點加入隊列que.push(root->right);  // 將右子樹頭結點加入隊列while (!que.empty()) {  // 接下來就要判斷這兩個樹是否相互翻轉TreeNode* leftNode = que.front(); que.pop();TreeNode* rightNode = que.front(); que.pop();if (!leftNode && !rightNode) {  // 左節點為空、右節點為空,此時說明是對稱的continue;}// 左右一個節點不為空,或者都不為空但數值不相同,返回falseif ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {return false;}que.push(leftNode->left);   // 加入左節點左孩子que.push(rightNode->right); // 加入右節點右孩子que.push(leftNode->right);  // 加入左節點右孩子que.push(rightNode->left);  // 加入右節點左孩子}return true;}
};

222.完全二叉樹的節點個數

給出一個完全二叉樹,求出該樹的節點個數。

在這里插入代碼片

示例 1:

輸入:root = [1,2,3,4,5,6]
輸出:6
示例 2:

輸入:root = []
輸出:0
示例 3:

輸入:root = [1]
輸出:1

思路:本題直接就是求有多少個節點,無腦存進結果變量就行了。

class Solution {
public:int countNodes(TreeNode* root) {if (root == nullptr) return 0;TreeNode* left = root->left;TreeNode* right = root->right;int leftDepth = 0, rightDepth = 0; // 這里初始為0是有目的的,為了下面求指數方便while (left) {  // 求左子樹深度left = left->left;leftDepth++;}while (right) { // 求右子樹深度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.平衡二叉樹

給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

本題中,一棵高度平衡二叉樹定義為:一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。

思路:比較高度,必然是要后序遍歷。

遞歸三步曲分析:
1.明確遞歸函數的參數和返回值
參數:當前傳入節點。 返回值:以當前傳入節點為根節點的樹的高度。
2.明確終止條件
遞歸的過程中依然是遇到空節點了為終止,返回0,表示當前節點為根節點的樹高度為0
3.明確單層遞歸的邏輯
如何判斷以當前傳入節點為根節點的二叉樹是否是平衡二叉樹呢?當然是其左子樹高度和其右子樹高度的差值。

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

class Solution {
public:// 返回以該節點為根節點的二叉樹的高度,如果不是平衡二叉樹了則返回-1int getHeight(TreeNode* node) {if (node == NULL) {return 0;}int leftHeight = getHeight(node->left);if (leftHeight == -1) return -1;int rightHeight = getHeight(node->right);if (rightHeight == -1) return -1;return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);}bool isBalanced(TreeNode* root) {return getHeight(root) == -1 ? false : true;}
};int getHeight(TreeNode* node) {if (node == NULL) {return 0;}int leftHeight = getHeight(node->left);if (leftHeight == -1) return -1;int rightHeight = getHeight(node->right);if (rightHeight == -1) return -1;return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);
}

257. 二叉樹的所有路徑

給定一個二叉樹,返回所有從根節點到葉子節點的路徑。

說明: 葉子節點是指沒有子節點的節點。

思路:把路徑記錄下來,需要回溯來回退一個路徑再進入另一個路徑。

在這里插入圖片描述

遞歸三部曲
1.遞歸函數參數以及返回值

傳入根節點,記錄每一條路徑的path,和存放結果集的result

2.確定遞歸終止條件

當 cur不為空,其左右孩子都為空的時候,就找到葉子節點。

3.確定單層遞歸邏輯

回溯要和遞歸永遠在一起

class Solution {
private:void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {path.push_back(cur->val); // 中,中為什么寫在這里,因為最后一個節點也要加入到path中 // 這才到了葉子節點if (cur->left == NULL && cur->right == NULL) {string sPath;for (int i = 0; i < path.size() - 1; i++) {sPath += to_string(path[i]);sPath += "->";}sPath += to_string(path[path.size() - 1]);result.push_back(sPath);return;}if (cur->left) { // 左 traversal(cur->left, path, result);path.pop_back(); // 回溯}if (cur->right) { // 右traversal(cur->right, path, result);path.pop_back(); // 回溯}}public:vector<string> binaryTreePaths(TreeNode* root) {vector<string> result;vector<int> path;if (root == NULL) return result;traversal(root, path, result);return result;}
};

404.左葉子之和

計算給定二叉樹的所有左葉子之和。

思路:如果該節點的左節點不為空,該節點的左節點的左節點為空,該節點的左節點的右節點為空,則找到了一個左葉子

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 && !root->left->left && !root->left->right) { // 左子樹就是一個左葉子的情況leftValue = root->left->val;}int rightValue = sumOfLeftLeaves(root->right);  // 右int sum = leftValue + rightValue;               // 中return sum;}
};

513.找樹左下角的值

給定一個二叉樹,在樹的最后一行找到最左邊的值。

思路:

class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);int result = 0;while (!que.empty()) {int size = que.size();for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();if (i == 0) result = node->val; // 記錄最后一行第一個元素if (node->left) que.push(node->left);if (node->right) que.push(node->right);}}return result;}
};

112. 路徑總和

給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等于目標和。

說明: 葉子節點是指沒有子節點的節點。

思路:

參數:需要二叉樹的根節點,還需要一個計數器,這個計數器用來計算二叉樹的一條邊之和是否正好是目標和,計數器為int型。
讓計數器count初始為目標和,然后每次減去遍歷路徑節點上的數值。
如果最后count == 0,同時到了葉子節點的話,說明找到了目標和。
回溯隱藏在traversal(cur->left, count - cur->left->val)這里, 因為把count - cur->left->val 直接作為參數傳進去,函數結束,count的數值沒有改變。

class Solution {
private:bool traversal(TreeNode* cur, int count) {if (!cur->left && !cur->right && count == 0) return true; // 遇到葉子節點,并且計數為0if (!cur->left && !cur->right) return false; // 遇到葉子節點直接返回if (cur->left) { // 左count -= cur->left->val; // 遞歸,處理節點;if (traversal(cur->left, count)) return true;count += cur->left->val; // 回溯,撤銷處理結果}if (cur->right) { // 右count -= cur->right->val; // 遞歸,處理節點;if (traversal(cur->right, count)) return true;count += cur->right->val; // 回溯,撤銷處理結果}return false;}public:bool hasPathSum(TreeNode* root, int sum) {if (root == NULL) return false;return traversal(root, sum - root->val);}
};

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

根據一棵樹的中序遍歷與后序遍歷構造二叉樹。

注意: 你可以假設樹中沒有重復的元素。

思路:

第一步:如果數組大小為零的話,說明是空節點了。

第二步:如果不為空,那么取后序數組最后一個元素作為節點元素。

第三步:找到后序數組最后一個元素在中序數組的位置,作為切割點

第四步:切割中序數組,切成中序左數組和中序右數組 (順序別搞反了,一定是先切中序數組)

第五步:切割后序數組,切成后序左數組和后序右數組

第六步:遞歸處理左區間和右區間

class Solution {
private:// 中序區間:[inorderBegin, inorderEnd),后序區間[postorderBegin, postorderEnd)TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& postorder, int postorderBegin, int postorderEnd) {if (postorderBegin == postorderEnd) return NULL;int rootValue = postorder[postorderEnd - 1];TreeNode* root = new TreeNode(rootValue);if (postorderEnd - postorderBegin == 1) return root;int delimiterIndex;for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break;}// 切割中序數組// 左中序區間,左閉右開[leftInorderBegin, leftInorderEnd)int leftInorderBegin = inorderBegin;int leftInorderEnd = delimiterIndex;// 右中序區間,左閉右開[rightInorderBegin, rightInorderEnd)int rightInorderBegin = delimiterIndex + 1;int rightInorderEnd = inorderEnd;// 切割后序數組// 左后序區間,左閉右開[leftPostorderBegin, leftPostorderEnd)int leftPostorderBegin =  postorderBegin;int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 終止位置是 需要加上 中序區間的大小size// 右后序區間,左閉右開[rightPostorderBegin, rightPostorderEnd)int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);int rightPostorderEnd = postorderEnd - 1; // 排除最后一個元素,已經作為節點了root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  postorder, leftPostorderBegin, leftPostorderEnd);root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);return root;}
public:TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if (inorder.size() == 0 || postorder.size() == 0) return NULL;// 左閉右開的原則return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());}
};

654.最大二叉樹

給定一個不含重復元素的整數數組。一個以此數組構建的最大二叉樹定義如下:

二叉樹的根是數組中的最大元素。
左子樹是通過數組中最大值左邊部分構造出的最大二叉樹。
右子樹是通過數組中最大值右邊部分構造出的最大二叉樹。
通過給定的數組構建最大二叉樹,并且輸出這個樹的根節點。

思路:構造樹一般采用的是前序遍歷,因為先構造中間節點,然后遞歸構造左子樹和右子樹。

class Solution {
private:// 在左閉右開區間[left, right),構造二叉樹TreeNode* traversal(vector<int>& nums, int left, int right) {if (left >= right) return nullptr;// 分割點下標:maxValueIndexint maxValueIndex = left;for (int i = left + 1; i < right; ++i) {if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;}TreeNode* root = new TreeNode(nums[maxValueIndex]);// 左閉右開:[left, maxValueIndex)root->left = traversal(nums, left, maxValueIndex);// 左閉右開:[maxValueIndex + 1, right)root->right = traversal(nums, maxValueIndex + 1, right);return root;}
public:TreeNode* constructMaximumBinaryTree(vector<int>& nums) {return traversal(nums, 0, nums.size());}
};

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

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

相關文章

Python+DRVT 從外部調用 Revit:批量創建樓板

今天繼續批量創建常用的基礎元素&#xff1a;樓板。這次以簡單的輪廓為矩形的樓板為例。讓我們來看一看如何讓Revit自動干活&#xff1a; from typing import List import math # drvt_pybind 支持多會話、多文檔&#xff0c;先從簡單的單會話、單文檔開始 # MyContext是在Pyt…

猿輔導數據分析面試題及參考答案

給定用戶成績表,編寫SQL查詢排名靠前的用戶(例如前10名),并說明rank()和dense_rank()的區別。 要查詢成績表中排名靠前的用戶(如前10名),需先明確排名依據(通常為成績降序),再通過排序和限制結果行數實現。假設用戶成績表名為user_scores,包含user_id(用戶ID)和s…

在樹莓派集群上部署 Distributed Llama (Qwen 3 14B) 詳細指南

項目地址&#xff1a;https://github.com/b4rtaz/distributed-llama 本文檔將指導您如何使用一個樹莓派5作為Root節點和三個樹莓派4作為Worker節點&#xff0c;共同搭建一個4節點的分布式LLM推理集群&#xff0c;并運行10.9GB的Qwen 3 14B模型。 中間要用到github和huggingface…

C++ 容器——unordered_xxx

自 C11 開始&#xff0c;STL 引入了基于 hash table 的 unordered_set、unordered_map 等容器&#xff0c;正如其名它們是無序容器。一定數量&#xff08;據說有測試數據是10000000&#xff09;元素時無序容器的性能要比對應的有序容器優。一、容器數據結構unordered_set、unor…

分布式常見面試題整理

一、分布式理論&#xff1a; CAP理論 分布式系統最多同時滿足一致性&#xff08;C&#xff09;、可用性&#xff08;A&#xff09;、分區容錯性&#xff08;P&#xff09;中的兩個&#xff0c;無法三者兼得。 BASE理論 對CAP中一致性和可用性的權衡&#xff0c;強調基本可用&a…

Python基礎入門常用198英語單詞詳解

最近&#xff0c;我總結了一份Python學習者入門常用單詞表&#xff0c;列出了Python學習中常見的198個高頻單詞&#xff0c;供初學者學習使用。 這些單詞都比較簡單&#xff0c;非常易于理解&#xff0c;在掌握好單詞的基礎上&#xff0c;再去學Python可以達到事半功倍的效果。…

EP-SPY 網路追蹤規避實驗:山脈通聯測試

EP-SPY V3.0 https://github.com/MartinxMax/ep-spy 基於 GI6E 編碼的無線電通信工具&#xff0c;用於保護您的隱私。 https://github.com/MartinxMax/gi6e 編寫了偽協議以防止內容被解密無法通過網絡追蹤&#xff0c;抵抗官方監控無線音頻廣播&#xff0c;用於隱蔽信息傳輸…

蘋果 FoundationModels 秘典俠客行:隱私為先的端側 AI 江湖

引子 話說俠客島之上&#xff0c;有一對年輕俠侶 ——「青鋒劍客」凌云與「素心仙子」蘇凝&#xff0c;二人自幼習武&#xff0c;尤擅拆解各路奇功秘籍。 近日聽聞蘋果谷&#xff08;Apple&#xff09;于 WWDC 2025 武林大會之上&#xff0c;亮出一門全新絕學「FoundationMod…

華為基于IPD的產品質量計劃模板

目錄 模板:產品質量計劃模板....................................... 1 1. 介紹...................................................................... 5 1.1. 范圍和目的.................................................... 5 1.2. 參考資料..…

事務管理的選擇:為何 @Transactional 并非萬能,TransactionTemplate 更值得信賴

在 Spring 生態的后端開發中&#xff0c;事務管理是保障數據一致性的核心環節。開發者常常會使用 Transactional 注解快速開啟事務&#xff0c;一行代碼似乎就能解決問題。但隨著業務復雜度提升&#xff0c;這種“簡單”的背后往往隱藏著難以察覺的隱患。本文將深入剖析 Spring…

CodePerfAI體驗:AI代碼性能分析工具如何高效排查性能瓶頸、優化SQL執行耗時?

前陣子幫同事排查用戶下單接口的性能問題時&#xff0c;我算是真切感受到 “找性能瓶頸比寫代碼還磨人”—— 接口偶爾會突然卡到 3 秒以上&#xff0c;查日志只看到 “SQL 執行耗時過長”&#xff0c;但具體是哪個查詢慢、為什么慢&#xff0c;翻了半天監控也沒頭緒&#xff0…

《sklearn機器學習——繪制分數以評估模型》驗證曲線、學習曲線

估計器的偏差、方差和噪聲 每一個估計器都有其優勢和劣勢。它的泛化誤差可以分解為偏差、方差和噪聲。估計器的偏差是不同訓練集的平均誤差。估計器的方差表示對不同訓練集&#xff0c;模型的敏感度。噪聲是數據的特質。 在下圖中&#xff0c;可以看見一個函數 f(x)cos?32πxf…

2025年AI PPT必修課-匯報中AI相關內容的“陷阱”與“亮點”

《2025年AI PPT必修課-匯報中AI相關內容的“陷阱”與“亮點”》 (適用于方案匯報、戰略PPT、標書/投資人演示)一、內容類坑&#xff08;戰略/趨勢層面&#xff09;? Pitfall (不要寫)? Correct Expression (推薦寫法)Why (原因)還在強調 Caffe / Theano / TF1.x / LSTM采用 P…

Java數據結構 - 順序表模擬實現與使用

目錄1.順序表的基本介紹2.順序表的模擬實現2.1 常見的功能2.2 基本框架2.3 方法的實現2.3.1 add方法2.3.2 size方法2.3.3 display方法2.3.4 add&#xff08;int pos&#xff0c;E data)方法2.3.5 remove方法2.3.6 get方法2.3.7 contain方法2.3.8 indexOf方法2.3.9 set方法2.3.1…

rust語言 (1.88) egui (0.32.1) 學習筆記(逐行注釋)(二十六)windows平臺運行時隱藏控制臺

1、主程序第一句添加&#xff1a; 必須放在所有代碼第一句 #![cfg_attr(windows, windows_subsystem "windows")]2、 編譯命令&#xff1a;cargo build --release3、 編譯完成后運行可執行文件&#xff1a; 項目目錄/target/release/項目名.exe

什么是靜態住宅IP 跨境電商為什么要用靜態住宅IP

靜態住宅IP的定義靜態住宅IP是指由互聯網服務提供商&#xff08;ISP&#xff09;分配給家庭用戶的固定IP地址。與動態IP不同&#xff0c;靜態IP不會頻繁變動&#xff0c;長期保持穩定。其特點包括&#xff1a;固定性&#xff1a;IP地址長期不變&#xff0c;適合需要穩定網絡環境…

RabbitMQ 初步認識

目錄 1. 基本概念 2. RabbitMq 的工作流程 3. 協議 4. 簡單的生產者, 消費者模型 4.1 我們先引入 rabbitmq 的依賴 4.2 生產者 4.3 消費者 1. 基本概念 Pruducer : 生產者, 產生消息Consumer : 消費者, 消費消息Broker : RabbitMq Server, 用來接收和發送消息Connectio…

Redis(46) 如何搭建Redis哨兵?

搭建 Redis 哨兵&#xff08;Sentinel&#xff09;集群&#xff0c;確保 Redis 服務具有高可用性。以下是詳細的步驟&#xff0c;從 Redis 安裝、配置主從復制到配置和啟動 Sentinel 集群&#xff0c;并結合相關的代碼示例。 步驟 1&#xff1a;安裝 Redis 首先&#xff0c;需要…

Grafana 多指標相乘

PromQL中多指標相乘 PromQL表達式&#xff1a; 0.045 * h9_daily_income{coin"nock"} * h9_pool_price_cny{coin"nock"}&#x1f4c8; 基礎&#xff1a;單指標運算 常數與指標相乘 在PromQL中&#xff0c;常數與指標的乘法是最簡單的運算&#xff1a; # ?…

【微服務】springboot3 集成 Flink CDC 1.17 實現mysql數據同步

目錄 一、前言 二、常用的數據同步解決方案 2.1 為什么需要數據同步 2.2 常用的數據同步方案 2.2.1 Debezium 2.2.2 DataX 2.2.3 Canal 2.2.4 Sqoop 2.2.5 Kettle 2.2.6 Flink CDC 三、Flink CDC介紹 3.1 Flink CDC 概述 3.1.1 Flink CDC 工作原理 3.2 Flink CDC…