【C】鏈式二叉樹算法題2

目錄

1? 另一棵樹的子樹?

?1)?題目描述

示例1:

示例2:

2) 算法解析

3) 代碼

2? 二叉樹的遍歷

1) 問題描述

2) 算法解析

3) 代碼

3? 總結??


1? 另一棵樹的子樹?

leetcode鏈接https://leetcode.cn/problems/subtree-of-another-tree/description/


?1)?題目描述

? 給你兩棵二叉樹?root?和?subRoot?。檢驗?root?中是否包含和?subRoot?具有相同結構和節點值的子樹。如果存在,返回?true?;否則,返回?false?。

? 二叉樹?tree?的一棵子樹包括?tree?的某個節點和這個節點的所有后代節點。tree?也可以看做它自身的一棵子樹。

示例1:

輸入:root = [3,4,5,1,2], subRoot = [4,1,2]
輸出:true

示例2:

輸入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
輸出:false

? 該題目是想讓你判斷 root 這棵樹中是否有 subRoot 這棵樹,不管是相同的樹,還是左子樹中有與subRoot 相同的樹或者是在右子樹中有與 subRoot 相同的樹,subRoot 都算是 root 的子樹。


2) 算法解析

? 該題目可以采用遞歸算法來解決。這道題的解決需要使用到前一篇文章里的相同的樹的算法,因為判斷 subRoot 是否是 root 的子樹,本質上就是判斷 root 里是否有與 subRoot 相同的樹,具體算法思想描述如下:
? 該遞歸算法可以抽象為 root 的左子樹里是否有與 subRoot 相同的樹或者右子樹里是否有與 subRoot 相同的樹,這個就是遞歸解決該問題的過程。邊界條件共有兩條:(1) 如果 root 本身是一棵空樹,那么 root 里肯定沒有與 subRoot 相同的樹,直接返回 false;(2) 如果 root 這棵樹本身就是與 subRoot 相同的樹,說明 subRoot 是 root 的一棵子樹,那就返回 true。


3) 代碼

typedef struct TreeNode TreeNode;//判斷相同的樹bool isSameTree(TreeNode* p, TreeNode* q){if (p == NULL && q == NULL){return true;}if (p == NULL || q == NULL){return false;}if (p->val != q->val){return false;}return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);}bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) 
{//如果root為空,那就返回falseif (root == NULL){return false;}//如果兩個結點對應的樹是相同的樹,返回trueif (isSameTree(root, subRoot)){return true;}//判斷subRoot是否是左子樹或者右子樹的子樹return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

2? 二叉樹的遍歷

leetcode鏈接https://leetcode.cn/problems/binary-tree-preorder-traversal/description/


1) 問題描述

? 給你二叉樹的根節點?root?,返回它節點值的?前序?遍歷。

? 這里看似是一個簡單的前序遍歷,但是其實沒有那么簡單,我們來看一下函數頭部:

int* preorderTraversal(struct TreeNode* root, int* returnSize) 
{}

? 可以看到其返回值為 int* ,也就是一個指針,并不像之前我們寫過的前序遍歷一樣返回值為 void。實際上這里是需要返回一個存儲了節點前序遍歷值的數組,所以返回值才為 int*。


2) 算法解析

? 這里最大的難點就在與如何將前序遍歷的結果存儲在數組里面,而且所給的函數頭部里面也有一個 returnSize 參數,通過名字可以看出來,該參數的作用實際上就是返回數組的大小,所以我們不僅需要將數組返回,還得計算數組中有多少元素,也就是二叉樹里面有多少節點。所以我們需要首先計算二叉樹里面節點的個數(在鏈式二叉樹文章中提到過相關操作的實現),所以這里總共需要 3 個函數:

(1) TreeSize函數:用來計算二叉樹里面節點的個數。

(2) PreOrder函數:用來進行前序遍歷,將結果存儲在數組中。

(3) preorderTraversal函數:用來創建數組,返回存儲結果的數組。

? 接下來我們來講解如何將前序遍歷的結果存儲在數組中。

? 可能開始我們想的是按照前序遍歷的代碼,只需將打印的地方改為向數組中存儲值即可:

void PreOrder(TreeNode* root, int* arr)
{int i = 0;if (root == NULL){return;}arr[i] = root->val;i++;PreOrder(root->left, arr);PreOrder(root->right, arr);
}

但是這樣會存在一個問題,就是在不斷遞歸的過程中,每次進入新的遞歸的時候,里面的 i 都會變成0,也就是總是往 arr[0] 位置存儲前序遍歷的結果,這里借助函數棧幀(每次調用函數時,會新開辟的一塊空間,每個函數的空間是獨立的)的概念來解釋:

可以看到每次調用PreOrder函數,都會新開辟一塊空間,所以其實里面的 i 都是屬于不用空間的,一個 i 改變并不會影響另一個函數里面的 i ,所以每次遞歸調用函數 i 都是為 0 的。

? 那么要想在遞歸過程中改變這個下標,我們就需要傳遞一個整形的地址,讓其能夠找到存儲 arr 下標的空間,讓存儲空間里面的值改變,就會讓下標隨著遞歸的而改變了

//arr為數組收元素的地址,pi為存儲arr數組下標的地址
void PreOrder(TreeNode* root, int* arr, int* pi)
{if (root == nullptr){return;}arr[(*pi)++] = root->val;PreOrder(root->left);PreOrder(root->right);
}

這里就可以通過一個指針變量 pi 來指向存儲 arr 數組下標的空間(傳參時傳遞一個值為 0 的整型的地址即可),?這樣通過 pi 就可以間接改變 arr 數組中的值了。


3) 代碼

typedef struct TreeNode TreeNode;//先計算樹的結點個數,依結點個數開辟數組空間int TreeSize(TreeNode* root){if (root == NULL){return 0;}return 1 + TreeSize(root->left) + TreeSize(root->right);}
//將前序遍歷的序列存入數組中
void PreOrder(TreeNode* root, int* arr, int* pi)
{if (root == NULL){return;}arr[(*pi)++] = root->val;//遍歷左子樹PreOrder(root->left, arr, pi);//遍歷右子樹PreOrder(root->right, arr, pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) 
{*returnSize = TreeSize(root);int* arr = (int*)malloc(sizeof(int) * (*returnSize));if (arr == NULL){perror("malloc fail!\n");exit(1);}int n = 0;PreOrder(root, arr, &n);return arr;
}

3? 總結??

? 在該題目中,我們解決了如何在遞歸過程中向數組中存儲數據的問題。只需用一個指針變量間接改變即可。所以以后如果遇到類似問題,一定要想到利用指針來改變下標。

? 當然,除了前序遍歷,還有中序遍歷和后序遍歷,在講解完前序遍歷之后,相信這兩個遍歷也很簡單了,可以自己嘗試一下:
中序遍歷https://leetcode.cn/problems/binary-tree-inorder-traversal/代碼:

typedef struct TreeNode TreeNode;//返回樹的結點個數int TreeSize(TreeNode* root){if (root == NULL){return 0;}return 1 + TreeSize(root->left) + TreeSize(root->right);}
//中序遍歷樹,把遍歷數據存放在數組里面
void InOrder(TreeNode* root, int* arr, int* pi)
{if (root == NULL){return;}InOrder(root->left, arr, pi);arr[(*pi)++] = root->val;InOrder(root->right, arr, pi);
}int* inorderTraversal(struct TreeNode* root, int* returnSize) 
{*returnSize = TreeSize(root);int* arr = (int*)malloc(sizeof(int) * (*returnSize));if (arr == NULL){perror("malloc fail!\n");exit(1);}int n = 0;InOrder(root, arr, &n);return arr;
}

后序遍歷https://leetcode.cn/problems/binary-tree-postorder-traversal/description/代碼:

typedef struct TreeNode TreeNode;//求節點個數int TreeSize(TreeNode* root){if (root == NULL){return 0;}return 1 + TreeSize(root->left) + TreeSize(root->right);}//二叉樹的后序遍歷并將遍歷結果保存到數組中
void PostOrder(int* arr, TreeNode* root, int* i)
{if (root == NULL){return;}//遍歷左子樹PostOrder(arr, root->left, i);//遍歷右子樹PostOrder(arr, root->right, i);arr[(*i)++] = root->val;}int* postorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize = TreeSize(root);//根據二叉樹節點空間開辟數組int* arr = (int*)malloc(sizeof(int) * (*returnSize));int i = 0;PostOrder(arr, root, &i);return arr;
}

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

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

相關文章

配置Hadoop集群

Hadoop的運行模式 本地運行:在一臺單機上運行,沒有分布式文件系統,直接讀寫本地操作系統的文件系統。特點:不對配置文件進行修改,Hadoop 不會啟動 偽分布式:也是在一臺單機上運行,但用不同的 …

python辦公自動化--數據可視化(pandas+matplotlib)--生成條形圖和餅狀圖

前言 前幾天我們學習了pandas讀取數據,還學習了如何用patplotlib繪制柱狀圖和折線圖。 今天我們繼續學習,如何繪制條形圖和餅狀圖。 一、課程回顧-pandas讀取數據 1.示例數據文件 這里我們用到的依舊是d盤底下的這個excel工作簿,這個工作簿…

基于大模型的結節性甲狀腺腫診療全流程預測與方案研究報告

目錄 一、引言 1.1 研究背景與目的 1.2 研究意義 1.3 國內外研究現狀 二、大模型預測原理與方法 2.1 相關大模型概述 2.2 數據收集與預處理 2.3 模型訓練與驗證 三、術前預測與評估 3.1 結節性質預測 3.1.1 良惡性判斷 3.1.2 與傳統診斷方法對比 3.2 手術風險預測…

不同開發語言對字符串的操作

一、字符串的訪問 Objective-C: 使用 characterAtIndex: 方法訪問字符。 NSString *str "Hello, World!"; unichar character [str characterAtIndex:0]; // 訪問第一個字符 H NSLog("%C", character); // 輸出: H NSString 內部存儲的是 UTF-16 編…

Java開發者如何接入并使用DeepSeek

目錄 一、準備工作 二、添加DeepSeek SDK依賴 三、初始化DeepSeek客戶端 四、數據上傳與查詢 五、數據處理與分析 六、實際應用案例 七、總結 【博主推薦】:最近發現了一個超棒的人工智能學習網站,內容通俗易懂,風格風趣幽默&#xff…

S19文件格式詳解:汽車ECU軟件升級中的核心鏡像格式

文章目錄 引言一、S19文件格式的起源與概述二、S19文件的核心結構三、S19在汽車ECU升級中的應用場景四、S19與其他格式的對比五、S19文件實例解析六、工具鏈支持與安全考量七、未來趨勢與挑戰結語引言 在汽車電子控制單元(ECU)的軟件升級過程中,S19文件(也稱為Motorola S-…

CTF雜項——[suctf 2019]簽到題

base64轉圖片 可以直接用隨波逐流 得到flag SUCTF{ffffffffT4nk}

【Python】整數除法不正確,少1的問題,以及有關浮點數轉換的精度問題

1. 問題 今天在做leetcode 不同路徑 的時候發現了個問題 對于m53 n4class Solution:def uniquePaths(self, m: int, n: int) -> int:rlt 1for i in range(0, m-1):rlt * (m n - 2 - i)for i in range(0, m-1):rlt / (i 1)return int(rlt)為什么這個結果是 26234class S…

AI無代碼平臺

以下是目前支持快速開發產品的高生產力免費AI無代碼平臺推薦,按功能和適用場景分類: 一、全棧應用開發類 Bolt.DIY DeepSeek-R1 無需編寫代碼即可開發全棧應用,提供免費API和無速率限制,支持AI編碼助手與自動化流程 。 優勢&…

Gini系數的應用 - 指標波動貢獻分析

基尼系數的定義 基尼系數是衡量數據分布不均衡程度的指標,取值范圍在0到1之間: 0 表示完全均衡(所有值相等)。1 表示完全不均衡(所有值集中在一個點)。 基尼系數的計算公式 假設有 n n n 個數據點&…

第一節: 網絡基礎與參考模型

深入理解OSI七層模型與TCP/IP四層模型:網絡工程師的入門指南 在網絡通信的世界中,OSI七層模型和TCP/IP四層模型是理解網絡架構的基礎。無論是配置路由器、排查網絡故障,還是設計復雜的網絡系統,掌握這些模型的分層結構及其功能都是必不可少的。本文將從新手角度出發,深入…

HTTP拾技雜談

HTTP拾技雜談 簡單聊聊HTTP中的那些東西 文章目錄 HTTP拾技雜談前言HTTP協議1.請求從客戶端到服務器端的4個步驟一般客戶端請求如下:服務端響應如下 2.Keep-AliveHTTP方法Cookie 總結 前言 超文本傳輸協議(Hypertext Transfer Protocol ,HT…

用Deepseek寫一個五子棋微信小程序

在當今快節奏的生活中,休閑小游戲成為了許多人放松心情的好選擇。五子棋作為一款經典的策略游戲,不僅規則簡單,還能鍛煉思維。最近,我借助 DeepSeek 的幫助,開發了一款五子棋微信小程序。在這篇文章中,我將…

自然語言處理:最大期望值算法

介紹 大家好,博主又來給大家分享知識了,今天給大家分享的內容是自然語言處理中的最大期望值算法。那么什么是最大期望值算法呢? 最大期望值算法,英文簡稱為EM算法,它的核心思想非常巧妙。它把求解模型參數的過程分成…

【從零開始學習計算機科學】計算機體系結構(一)計算機體系結構、指令、指令集(ISA)與量化評估

【從零開始學習計算機科學】計算機體系結構(一)計算機體系結構、指令、指令集(ISA)與量化評估 概論計算機體系結構簡介計算機的分類并行體系結構指令集體系結構(ISA)分類存儲器尋址尋址模式操作數大小指令ISA的編碼程序的優化計算機體系結構量化評估存儲器體系結構概論 …

Electron使用WebAssembly實現CRC-32 常用標準校驗

Electron使用WebAssembly實現CRC-32 常用標準校驗 將C/C語言代碼,經由WebAssembly編譯為庫函數,可以在JS語言環境進行調用。這里介紹在Electron工具環境使用WebAssembly調用CRC-32 常用標準格式校驗的方式。 CRC-32 常用標準校驗函數WebAssembly源文件…

Docker基礎篇——Ubuntu下Docker安裝

大家好我是木木,在當今快速發展的云計算與云原生時代,容器化技術蓬勃興起,Docker 作為實現容器化的主流工具之一,為開發者和運維人員帶來了極大的便捷 。下面我們一起進行Docker安裝。 Docker的官方Ubuntu安裝文檔,如…

第五課:Express框架與RESTful API設計:技術實踐與探索

在使用Node.js進行企業應用開發,常用的開發框架Express,其中的中間件、路由配置與參數解析、RESTful API核心技術尤為重要,本文將深入探討它們在應用開發中的具體使用方法,最后通過Postman來對開發的接口進行測試。 一、Express中…

mitmproxy配合Wireshark 抓包分析

Mitmproxy 是一款非常強大的 交互式 HTTP 代理 工具,它被廣泛應用于 Web 開發、API 調試、安全測試 等領域。與 Wireshark 側重于被動監聽網絡流量不同,Mitmproxy 更像一個 主動的中間人,可以攔截、檢查、修改和重放 HTTP/HTTPS 流量&#xf…

Varlens(手機上的單反)Ver.1.9.3 高級版.apk

Varlens 是一款專業級手機攝影軟件,旨在通過豐富的功能和高自由度參數調節,讓手機拍攝效果媲美微單相機。以下是核心功能總結: 一、核心功能 專業拍攝模式 支持手動/自動/程序模式,可調節ISO、快門速度、EV、白平衡等參數27 提供…