每日一題——力扣144. 二叉樹的前序遍歷(舉一反三+思想解讀+逐步優化)五千字好文


一個認為一切根源都是“自己不夠強”的INTJ

個人主頁:用哲學編程-CSDN博客
專欄:每日一題——舉一反三
Python編程學習
Python內置函數

Python-3.12.0文檔解讀

目錄

?我的寫法:

代碼結構

時間復雜度

空間復雜度

總結

我要更強

代碼說明

時間復雜度

空間復雜度

哲學和編程思想

迭代與遞歸:

空間與時間的權衡:

抽象與具體化:

數據結構的選擇:

內存管理:

算法優化:

舉一反三


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

?我的寫法:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
int TreeSize(struct TreeNode* root){return root == NULL ? 0 :1+TreeSize(root->left)+TreeSize(root->right);
}void perorder(struct TreeNode* root,int* a,int* pi){if(root==NULL)return;a[(*pi)++]=root->val;perorder(root->left,a,pi);perorder(root->right,a,pi);
}int* preorderTraversal(struct TreeNode* root, int* returnSize){*returnSize=TreeSize(root);int* a=(int*)malloc(*returnSize*sizeof(int));int i=0;perorder(root,a,&i);return a;
}

這段代碼實現了二叉樹的前序遍歷(Preorder Traversal),并返回一個包含遍歷結果的動態數組。下面是對這段代碼的專業點評:

代碼結構

  1. TreeSize 函數:
    • 該函數用于計算二叉樹的節點數量。它通過遞歸地遍歷左子樹和右子樹,并累加節點數來實現。如果根節點為空,則返回0;否則,返回1加上左子樹和右子樹的節點數。
  2. perorder 函數:
    • 這是一個遞歸函數,用于執行前序遍歷。前序遍歷的順序是:根節點 -> 左子樹 -> 右子樹。該函數將遍歷到的節點值存儲到數組?a?中,并通過引用傳遞的?pi?指針來更新數組索引。
  3. preorderTraversal 函數:
  • 這是主函數,負責分配返回數組的空間,調用?perorder?函數進行遍歷,并返回遍歷結果。它首先通過?TreeSize?函數確定返回數組的大小,然后分配相應大小的內存空間,并調用?perorder?函數填充數組。

時間復雜度

  • TreeSize 函數:O(n),其中 n 是樹中的節點數。每個節點都被訪問一次。
  • perorder 函數:O(n),同樣地,每個節點都被訪問一次。
  • preorderTraversal 函數:O(n),因為它調用了?perorder?函數,而?perorder?函數的時間復雜度是 O(n)。

空間復雜度

  • TreeSize 函數:O(h),其中 h 是樹的高度。在最壞的情況下,遞歸調用的棧深度等于樹的高度。
  • perorder 函數:O(h),同樣地,遞歸調用的棧深度等于樹的高度。
  • preorderTraversal 函數:O(n),因為需要分配一個大小為 n 的數組來存儲遍歷結果。此外,遞歸調用的棧空間也是 O(h)。

總結

這段代碼有效地實現了二叉樹的前序遍歷,并且時間復雜度和空間復雜度都是合理的。注意,空間復雜度中的 O(h) 部分是由于遞歸調用棧的使用,這在樹的高度較大時可能會成為一個問題。在實際應用中,需要考慮樹的平衡性以及可能的最大高度。


我要更強

為了優化時間復雜度和空間復雜度,我們可以考慮使用迭代方法而不是遞歸來實現前序遍歷。這樣可以避免遞歸調用棧的空間開銷,并且時間復雜度仍然是 O(n),因為每個節點仍然只被訪問一次。

下面是使用迭代方法實現的完整代碼:

#include <stdlib.h>
#include <stdbool.h>struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
};int* preorderTraversal(struct TreeNode* root, int* returnSize) {if (root == NULL) {*returnSize = 0;return NULL;}int* result = (int*)malloc(100 * sizeof(int)); // 假設最多100個節點,可根據實際情況調整struct TreeNode** stack = (struct TreeNode**)malloc(100 * sizeof(struct TreeNode*)); // 棧空間int top = -1; // 棧頂指針int index = 0; // 結果數組索引stack[++top] = root; // 根節點入棧while (top >= 0) {struct TreeNode* node = stack[top--]; // 出棧result[index++] = node->val; // 訪問節點// 由于前序遍歷是根-左-右,先右子樹入棧,再左子樹入棧if (node->right != NULL) {stack[++top] = node->right;}if (node->left != NULL) {stack[++top] = node->left;}}*returnSize = index; // 設置返回數組大小free(stack); // 釋放棧空間return result;
}

代碼說明

  1. 棧的使用:我們使用一個棧來模擬遞歸調用的過程。在迭代方法中,我們手動管理這個棧。
  2. 前序遍歷的順序:根節點首先被訪問,然后是左子樹,最后是右子樹。因此,我們在棧中先壓入右子樹,然后是左子樹,這樣在出棧時,左子樹會在右子樹之前被訪問。
  3. 內存管理:我們動態分配了棧和結果數組的空間。在函數結束前,我們釋放了棧的空間,但結果數組的空間由調用者負責釋放。

時間復雜度

  • O(n):每個節點被訪問一次。

空間復雜度

  • O(h):在最壞情況下,棧的大小等于樹的高度。在最好情況下(平衡樹),空間復雜度為 O(log n)。

這種方法在空間效率上優于遞歸方法,因為它避免了遞歸調用棧的空間開銷。然而,它仍然需要一個棧來模擬遞歸過程,因此在最壞情況下的空間復雜度仍然是 O(h)。如果樹非常不平衡,這可能會導致較高的空間使用。


哲學和編程思想

這些方法體現了以下哲學和編程思想:

  1. 迭代與遞歸:

    • 遞歸是一種自我調用的方法,它依賴于調用棧來保存狀態。遞歸通常使得代碼更簡潔、易于理解,但在處理大量數據時可能會導致棧溢出。
    • 迭代是一種循環結構,它通過顯式地管理狀態來避免遞歸的缺點。迭代通常更節省空間,因為它不需要額外的棧空間來保存中間狀態。
    • 在上述代碼中,我們使用了迭代方法來實現前序遍歷,這體現了在空間效率和性能之間的權衡。
  2. 空間與時間的權衡:

    • 在編程中,我們經常需要在空間復雜度和時間復雜度之間做出權衡。例如,使用額外的空間(如棧)來存儲中間結果,可以減少時間復雜度。
    • 在迭代方法中,我們犧牲了一定的空間(棧空間)來減少遞歸調用棧的空間開銷,從而優化了整體的空間復雜度。
  3. 抽象與具體化:

    • 抽象是指忽略問題的某些細節,專注于核心概念。在二叉樹遍歷中,我們抽象出了遍歷的順序(根-左-右),而不關心具體的實現細節。
    • 具體化是指將抽象的概念轉化為具體的實現。在迭代方法中,我們將抽象的遍歷順序具體化為棧的操作,通過入棧和出棧來實現遍歷。
  4. 數據結構的選擇:

    • 選擇合適的數據結構是編程中的一個重要決策。在二叉樹遍歷中,我們選擇了棧作為輔助數據結構,因為它可以有效地存儲和訪問節點的順序。
    • 棧的先進后出(LIFO)特性非常適合模擬遞歸調用的過程,使得我們可以在迭代中實現與遞歸相同的前序遍歷順序。
  5. 內存管理:

    • 在C語言中,內存管理是一個重要的編程實踐。我們手動分配和釋放內存,以避免內存泄漏和懸掛指針。
    • 在代碼中,我們動態分配了棧和結果數組的空間,并在不再需要時釋放了棧的空間,這體現了良好的內存管理習慣。
  6. 算法優化:

  • 算法優化是提高程序效率的關鍵。在迭代方法中,我們通過優化棧的使用順序(先右后左)來確保前序遍歷的正確性,這是一種算法層面的優化。

這些哲學和編程思想是解決復雜問題的基石,它們幫助我們在設計和實現代碼時做出明智的決策,以達到高效、可維護和可擴展的解決方案。


舉一反三

根據上述哲學和編程思想,以下是一些技巧和策略,可以幫助在面對類似問題時舉一反三:

  1. 理解問題本質:
    • 在解決任何問題之前,首先要深入理解問題的本質。例如,在二叉樹遍歷問題中,理解前序遍歷的定義(根-左-右)是至關重要的。
    • 技巧:將問題抽象為基本概念,然后從這些概念出發尋找解決方案。
  2. 選擇合適的數據結構:
    • 根據問題的特點選擇合適的數據結構。例如,棧在處理需要逆序操作的問題時非常有用。
    • 技巧:熟悉各種數據結構的特性,并能夠根據問題的需求靈活選擇。
  3. 迭代與遞歸的轉換:
    • 學會將遞歸算法轉換為迭代算法,或者反之。這種轉換通常涉及到使用棧或隊列來模擬遞歸調用棧。
    • 技巧:練習將遞歸算法重寫為迭代算法,以提高對這兩種方法的理解和應用能力。
  4. 空間與時間的權衡:
    • 在設計算法時,考慮時間和空間的權衡。有時候,犧牲一些空間可以顯著提高時間效率。
    • 技巧:評估不同解決方案的時間和空間復雜度,選擇最合適的平衡點。
  5. 內存管理:
    • 在需要手動管理內存的編程語言中,如C語言,注意內存的分配和釋放。
    • 技巧:養成良好的內存管理習慣,確保在不再需要內存時及時釋放。
  6. 算法優化:
    • 不斷尋找算法優化的可能性。例如,通過改變數據結構的使用順序或方式來提高效率。
    • 技巧:分析算法的瓶頸,嘗試不同的優化策略,如減少不必要的計算或改進數據訪問模式。
  7. 抽象與具體化:
    • 學會將復雜問題抽象為簡單的模型,然后將這些模型具體化為可執行的代碼。
    • 技巧:練習將問題分解為更小、更易于管理的部分,然后逐步構建解決方案。
  8. 代碼復用與模塊化:
    • 在編寫代碼時,考慮代碼的復用性和模塊化。這有助于提高代碼的可維護性和可擴展性。
    • 技巧:設計可重用的函數和類,將代碼分解為獨立的模塊。
  9. 測試與調試:
  • 編寫測試用例來驗證代碼的正確性,并使用調試工具來定位和修復錯誤。
  • 技巧:編寫全面的測試用例,使用調試工具逐步跟蹤代碼執行過程。

通過實踐這些技巧和策略,將能夠更好地理解和解決各種編程問題,提高你的編程能力和問題解決能力。記住,編程是一個不斷學習和實踐的過程,通過不斷的練習和挑戰,將能夠舉一反三,解決更復雜的問題。


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

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

相關文章

C語言力扣刷題7——刪除排序鏈表中的重復元素 II——[快慢雙指針法]

力扣刷題7——刪除排序鏈表中的重復元素 II——[快慢雙指針法] 一、博客聲明二、題目描述三、解題思路1、思路說明 四、解題代碼&#xff08;附注釋&#xff09; 一、博客聲明 找工作逃不過刷題&#xff0c;為了更好的督促自己學習以及理解力扣大佬們的解題思路&#xff0c;開辟…

好書安利 | LangChain入門指南:構建高可復用、可擴展的LLM應用程序(送PDF)輕松入門LangChain

《LangChain入門指南》 LangChain作為大模型集成框架鼎鼎大名&#xff0c;這本《LangChain入門指南》是一本很及時的書&#xff0c;值得推薦&#xff5e; 01 為什么需要LangChain 首先想象一個開發者在構建一個LLM應用時的常見場景。 當你開始構建一個新項目時&#xff0c;…

不使用canvs也能創建出點狀背景

div{ height: 100%; touch-action: none; background: radial-gradient(circle, #e6e6e6 1px, transparent 1px); /* 創建一個點狀背景 */ background-size: 15px 15px; /* 控制點的大小和間距 */ padding: 20px; /* 添加內邊距使內容不靠邊 */ position: relative; /* 讓內部內…

樹形DP——AcWing 323. 戰略游戲

樹形DP 定義 樹形動態規劃&#xff08;Tree Dynamic Programming&#xff0c;簡稱樹形DP&#xff09;是一種在樹形結構上應用動態規劃算法的技術。它利用樹的遞歸結構&#xff0c;通過定義狀態和狀態轉移方程&#xff0c;來求解與樹相關的最優化問題&#xff0c;如樹上的最長…

10秒教會你mysql的連接

連接MySQL數據庫通常可以通過多種方法實現&#xff0c;以下是幾種常見的方法&#xff0c;我將按照您的要求以清晰、分點的方式歸納說明&#xff1a; 1. 使用MySQL命令行客戶端 打開終端或命令提示符&#xff1a;首先&#xff0c;打開您的計算機上的終端或命令提示符窗口。輸入…

CSS中的display屬性:布局控制的關鍵

CSS的display屬性是控制元素在頁面上如何顯示的核心屬性之一。它決定了元素的顯示類型&#xff0c;以及它在頁面布局中的行為。本文將詳細介紹display屬性的不同值及其使用場景&#xff0c;幫助你更好地掌握布局控制。 display屬性的基本值 block 特點&#xff1a;塊級元素&…

LeetCode每日一題 2734.子串操作后的字典序最小字符串|標志位遍歷字符數組

問題描述 &#x1f4cb; 子串操作后的字典序最小字符串 給定一個僅包含小寫字母的字符串&#xff0c;你可以執行如下操作任意次&#xff1a; 選擇某個子串&#xff0c;將其中的每個字符都替換成其前一個字母&#xff08;比如 ‘b’ 變成 ‘a’&#xff0c;‘c’ 變成 ‘b’&…

未來數據中心智能運維的趨勢

隨著信息技術的飛速發展&#xff0c;數據中心作為支撐企業信息化建設的核心樞紐&#xff0c;其運維管理的重要性日益凸顯。傳統的運維模式已難以滿足現代數據中心高效、安全、靈活的需求&#xff0c;而智能運維正成為行業發展的新趨勢。本文將結合運維行業的資料和團隊經驗&…

【JavaScript 小工具】——如何判斷當前頁面是否在微信瀏覽器中打開

要判斷用戶是否通過微信瀏覽器打開網頁&#xff0c;你可以檢查用戶代理&#xff08;User Agent&#xff09;字符串中是否包含微信瀏覽器的特定標識。微信瀏覽器通常會在User Agent中包含"MicroMessenger"這個關鍵詞。 以下是一段JavaScript代碼示例&#xff0c;用于…

不使用cmake,如何在vs2019對cpp項目進行文件夾分類?

不使用cmake&#xff0c;如何在vs2019對cpp項目進行文件夾分類&#xff1f; 1.不使用cmake的根目錄指的是哪里&#xff1f;2.什么時候進行項目管理&#xff1f;3.應該分成什么樣的文件夾&#xff1f;4.如何分類&#xff1f; 1.不使用cmake的根目錄指的是哪里&#xff1f; 查看項…

最新AI智能聊天對話問答系統源碼(圖文搭建部署教程)+AI繪畫,文生圖,TTS語音識別輸入,文檔分析

一、人工智能語言模型和AI繪畫在多個領域廣泛應用 人工智能語言模型和AI繪畫在多個領域都有廣泛的應用。以下是一些它們的主要用處&#xff1a; 人工智能語言模型 內容生成 寫作輔助&#xff1a;幫助撰寫文章、博客、報告、劇本等。 代碼生成&#xff1a;自動生成或補全代碼&…

sudo: /etc/init.d/ssh: command not found

在 WSL 中嘗試啟動 SSH 服務時遇到 sudo: /etc/init.d/ssh: command not found 錯誤 安裝 OpenSSH 服務器 更新軟件包列表 sudo apt update安裝 OpenSSH 服務器 sudo apt install openssh-server啟動 SSH 服務 在 WSL 2 上,服務管理與傳統 Linux 系統有所不同。你可以手動啟動…

C++之STL(十)

1、適配器 2、函數適配器 #include <iostream> using namespace std;#include <algorithm> #include <vector> #include <functional>bool isOdd(int n) {return n % 2 1; } int main() {int a[] {1, 2, 3, 4, 5};vector <int> v(a, a 5);cou…

ONLYOFFICE 8.1版本桌面編輯器測評:重塑辦公效率的巔峰之作

在數字化辦公日益普及的今天&#xff0c;一款高效、便捷且功能強大的桌面編輯器成為了職場人士不可或缺的工具。ONLYOFFICE 8.1版本桌面編輯器憑借其卓越的性能和豐富的功能&#xff0c;成功吸引了眾多用戶的目光。今天&#xff0c;我們將對ONLYOFFICE 8.1版本桌面編輯器進行全…

使用el-amap-info-window遇到的問題

使用的這個庫https://github.com/yangyanggu/vue-amap 想要滾動amapInfoWindow里的內容&#xff0c;但不觸發地圖縮放 默認滾動amapInfoWindow里的內容&#xff0c;會觸發地圖縮放。看了C站一個大佬的文章解決了。 amapInfoWindow會自動滾動到頂部 我的amapInfoWindow里面用了…

【智能制造-4】機器人控制器

機器人控制器中分哪幾個模塊&#xff1f; 機器人控制器通常由以下幾個主要模塊組成: 運動控制模塊: 負責機器人各軸電機的位置、速度、加速度等控制 實現機器人末端執行器的精確定位和運動控制傳感器接口模塊: 負責機器人各種傳感器信號的采集和處理 為運動控制、環境感知等提…

Python-正則表達式

目錄 一、打開正則表達式 二、正則表達式的使用 1、限定符 &#xff08;1&#xff09;x*&#xff1a;*表示它前面的字符y 可以有0個或多個&#xff1b; &#xff08;2&#xff09;x&#xff1a;表示它前面的字符可以出現一次以上&#xff1b;&#xff08;只可以匹配多次&…

電鍍用開關電源技術詳解

1 引言 在電鍍行業里&#xff0c;一般要求工作電源的輸出電壓較低&#xff0c;而電流很大。電源的功率要求也比較高&#xff0c;一般都是幾千瓦到幾十千瓦。目前&#xff0c;如此大功率的電鍍電源一般都采用晶閘管相控整流方式。其缺點是體積大、效率低、噪音高、功率因數低、…

[CocosCreator]CocosCreator網絡通信:https + websocket + protobuf

環境 cocos creator版本&#xff1a;3.8.0 開發語言&#xff1a;ts 操作系統&#xff1a;windows http部分 直接使用 XMLHttpRequest 創建http請求 // _getHttpUrl 方法自己寫字符串拼接public httpPostJsonRequest(uri: string, headData: any, data: any, cb: Function…

2024年6月大眾點評深圳餐飲店鋪POI分析18萬家

2024年6月大眾點評深圳餐飲店鋪POI共有178720家 店鋪POI點位示例&#xff1a; 店鋪id G9TSD2JvdLtA7fdm 店鋪名稱 江味龍蝦館(南山店) 十分制服務評分 8.8 十分制環境評分 8.8 十分制劃算評分 8.6 人均價格 128 評價數量 12840 店鋪地址 南山大道與桂廟路交叉口西北角…