算法高頻題

  • 刷題LeetCode(Top 100-150題,至少刷兩遍)。重點:鏈表、樹、二分查找、動態規劃、回溯、棧/隊列。

  • 每一個題型,前10個高頻題

算法思考框架參考:算法題思維框架-CSDN博客

高頻順序參考網站:CodeTop 面試題目總結

1.樹

1.1102. 二叉樹的層序遍歷 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-level-order-traversal/

思考:題目已經給出層序遍歷,按照思考框架。

BFS:

 vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};vector<vector<int>> ans;queue<TreeNode*> q;q.push(root);while(!q.empty()){int levelSize = q.size();vector<int> layer;for(int i = 0;i<levelSize;++i){auto node = q.front();q.pop();// process node->vallayer.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}// current layer is overans.push_back(layer);}return ans;}

DFS:需要記錄深度depth,回溯時根據depth添加到對應數組里。

class Solution {
public:vector<vector<int>> ans;void dfs(TreeNode* root,int depth){if(!root) return;if(depth>=ans.size()){ans.push_back({root->val});}else{ans[depth].push_back(root->val);}dfs(root->left,depth+1);dfs(root->right,depth+1);}vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};dfs(root,0);return ans;}
};

1.2236. 二叉樹的最近公共祖先 - 力扣(LeetCode)https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

思考:按照思維框架,我們可以看出先需要知道左右子樹,顯然是后續遍歷。

具體思路:

  1. 如果當前節點為nullptr,返回nullptr。
  2. 如果當前節點就是p或q,那么返回當前節點。
  3. 遞歸遍歷左子樹和右子樹,得到左右子樹的結果。
  4. 如果左子樹和右子樹的結果都不為空,說明當前節點就是p和q的最近公共祖先。
  5. 如果左子樹結果不為空,右子樹結果為空,說明p和q都在左子樹中,返回左子樹的結果。
  6. 如果右子樹結果不為空,左子樹結果為空,說明p和q都在右子樹中,返回右子樹的結果。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == nullptr || root == p || root == q){return root;}TreeNode* left = lowestCommonAncestor(root->left,p,q);TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left!=nullptr && right!=nullptr){return root;}return left!=nullptr?left:right;}

時間復雜度:O(N),最壞情況下,我們需要訪問所有節點。

空間復雜度:O(H),遞歸調用的棧深度取決于二叉樹的高度,最壞情況下(樹退化為鏈表)為 O(N),平均情況下為 O(logN)。

1.3103. 二叉樹的鋸齒形層序遍歷 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/description/

這道題BFS的變種,核心思路仍然仍按層遍歷,但需要根據層數的奇偶性來決定遍歷方向:

  1. 使用隊列進行BFS:標準的層序遍歷方法

  2. 使用標志位記錄方向:用一個布爾值?leftToRight?記錄當前層應該是從左到右還是從右到左

  3. 根據方向處理每層結果

    • 如果是左到右:直接按遍歷順序加入結果

    • 如果是右到左:將當前層的結果反轉后加入結果

方法一:標準BFS + 反轉

vector<vector<int>> zigzagLevelOrder(TreeNode* root) {if(!root) return {};vector<vector<int>> res;queue<TreeNode*> q;q.push(root);bool leftToRight = true;while(!q.empty()){int levelSize = q.size();vector<int> layer(levelSize);for(int i = 0;i<levelSize;++i){auto node = q.front();q.pop();int index = leftToRight?i:levelSize-1-i;layer[index] = node->val;if(node->left) q.push(node->left);if(node->right) q.push(node->right);}res.push_back(layer);leftToRight = !leftToRight;}return res;}
  • 時間復雜度:O(n)

  • 空間復雜度:O(n)

方法二:使用雙端隊列(Deque)

這種方法更高效,避免了反轉操作:

class Solution {
public:vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> result;if (!root) return result;deque<TreeNode*> dq;dq.push_back(root);bool leftToRight = true;while (!dq.empty()) {int levelSize = dq.size();vector<int> currentLevel;for (int i = 0; i < levelSize; i++) {if (leftToRight) {// 從左到右:從前面取,往后面加(先左后右)TreeNode* node = dq.front();dq.pop_front();currentLevel.push_back(node->val);if (node->left) dq.push_back(node->left);if (node->right) dq.push_back(node->right);} else {// 從右到左:從后面取,往前面加(先右后左)TreeNode* node = dq.back();dq.pop_back();currentLevel.push_back(node->val);if (node->right) dq.push_front(node->right);if (node->left) dq.push_front(node->left);}}result.push_back(currentLevel);leftToRight = !leftToRight;}return result;}
};

?方法三:DFS遞歸解法

class Solution {
public:vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> result;dfs(root, 0, result);return result;}void dfs(TreeNode* node, int level, vector<vector<int>>& result) {if (!node) return;if (level >= result.size()) {result.push_back({});}if (level % 2 == 0) {// 偶數層:從左到右result[level].push_back(node->val);} else {// 奇數層:從右到左,插入到開頭result[level].insert(result[level].begin(), node->val);}dfs(node->left, level + 1, result);dfs(node->right, level + 1, result);}
};

時間復雜度:O(N),每個節點被訪問一次
空間復雜度:O(N),隊列或遞歸棧的空間

1.4124. 二叉樹中的最大路徑和 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-maximum-path-sum/

思路:

采用后序遍歷的遞歸方法:

  1. 遞歸函數定義maxGain(TreeNode* node)?返回以該節點為起點的最大路徑和(只能向下走)

  2. 計算當前節點的貢獻值

    • 左子樹的貢獻:leftGain = max(maxGain(node->left), 0)

    • 右子樹的貢獻:rightGain = max(maxGain(node->right), 0)

  3. 更新全局最大值node->val + leftGain + rightGain

  4. 返回當前節點的最大貢獻node->val + max(leftGain, rightGain)

class Solution {
private:int maxSum = INT_MIN;public:int maxPathSum(TreeNode* root) {maxGain(root);return maxSum;}int maxGain(TreeNode* node) {if (!node) return 0;// 遞歸計算左右子樹的最大貢獻值,如果為負則取0(相當于不選擇)int leftGain = max(maxGain(node->left), 0);int rightGain = max(maxGain(node->right), 0);// 當前節點作為轉折點的路徑和int priceNewPath = node->val + leftGain + rightGain;// 更新全局最大值maxSum = max(maxSum, priceNewPath);// 返回當前節點的最大貢獻(只能選擇一邊)return node->val + max(leftGain, rightGain);}
};
  • 時間復雜度:O(N),每個節點訪問一次

  • 空間復雜度:O(H),遞歸棧的深度,H為樹的高度

1.5

199. 二叉樹的右視圖 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-right-side-view/思路:

這道題要求從右側觀察二叉樹時能看到的節點,實際上就是求每一層最右邊的節點

主要有兩種方法:

  1. BFS層序遍歷:記錄每層的最后一個節點

  2. DFS遞歸:按照根→右→左的順序遍歷,記錄每層第一個訪問到的節點

方法一:BFS層序遍歷(推薦)

ector<int> rightSideView(TreeNode* root) {vector<int> result;if (!root) return result;queue<TreeNode*> q;q.push(root);while (!q.empty()) {int levelSize = q.size();for (int i = 0; i < levelSize; i++) {TreeNode* node = q.front();q.pop();// 如果是當前層的最后一個節點,加入結果if (i == levelSize - 1) {result.push_back(node->val);}if (node->left) q.push(node->left);if (node->right) q.push(node->right);}}return result;}

方法二:DFS遞歸

思路:按照根→右→左的順序遍歷,每層第一個訪問到的節點就是右視圖能看到的節點。

class Solution {
public:vector<int> rightSideView(TreeNode* root) {vector<int> result;dfs(root, 0, result);return result;}void dfs(TreeNode* node, int depth, vector<int>& result) {if (!node) return;// 如果當前深度等于結果數組大小,說明是這一層第一個訪問的節點(最右邊)if (depth == result.size()) {result.push_back(node->val);}// 先遞歸右子樹,再遞歸左子樹dfs(node->right, depth + 1, result);dfs(node->left, depth + 1, result);}
};
  • 時間復雜度:O(N),每個節點訪問一次

  • 空間復雜度

    • BFS:O(W),W為樹的最大寬度

    • DFS:O(H),H為樹的高度(遞歸棧深度)

1.694. 二叉樹的中序遍歷 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-inorder-traversal/

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

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

相關文章

服務器安裝 LDOPE(MODIS 數據處理工具)

目錄下載方式1-&#xff08;簡單快捷&#xff09;根據WRF-VPRM 需要打補丁下載方式2&#xff1a;&#xff08;手動安裝依賴&#xff09;一、安裝所需依賴庫&#xff08;4 個主庫 2 個基礎庫&#xff09;另- HDF-EOS 手動編譯二、解壓并安裝 LDOPE參考下載方式1-&#xff08;簡…

克隆代幣 + 捆綁開盤:多鏈環境下的低成本發幣玩法

在加密世界&#xff0c;發幣已經不再是“少數開發者的專利”。隨著工具的普及&#xff0c;任何人都可以快速發行一個在加密世界&#xff0c;發幣已經不再是“少數開發者的專利”。隨著工具的普及&#xff0c;任何人都可以快速發行一個代幣。但問題是&#xff1a;如何在保證低成…

數據結構中的 二叉樹

1.前言 在 Java 中&#xff0c;樹&#xff08;Tree&#xff09;是一種非線性數據結構&#xff0c;由節點&#xff08;Node&#xff09;組成&#xff0c;常見的線性表則是我們之前學過的順序表、鏈表、棧、隊列等等。每個節點包含數據和指向子節點的引用。樹的常見實現方式包括二…

IntelliJ IDEA 啟動項目時配置端口指南

&#x1f31f; 一、為什么需要手動設置啟動端口&#xff1f; 默認情況下&#xff0c;Spring Boot 應用會使用 8080 端口啟動。但在以下場景中&#xff0c;我們必須自定義端口&#xff1a; 多個微服務同時運行&#xff0c;需避免端口沖突&#xff1b;團隊協作開發&#xff0c;統…

spark sql之from_json函數

目錄前言函數語法參數說明返回值案例案例1案例2前言 在Spark SQL中&#xff0c;from_json函數用于解析包含JSON字符串的列&#xff0c;并將其轉換為Spark SQL的結構化類型&#xff08;如struct、map或array&#xff09; 函數語法 from_json(jsonStr, schema [, options])參數…

數據結構 之 【位圖的簡介】

目錄 1.位圖的引入 2.位圖概念 3.位圖的實現 3.1前提準備 3.2set 3.3reset 3.4test 4.位圖的應用 1.位圖的引入 給40億個不重復的無符號整數&#xff0c;沒排過序 再給一個無符號整數&#xff0c;如何快速判斷這個無符號整數是否在 這40億個數中 首先&#xff0c;一個…

[iOS] ViewController 的生命周期

文章目錄前言一、UIViewController 生命周期有關函數二、UIViewController 中函數的執行順序運行結果1.present和dismiss2.push和pop三、總結前言 UIViewController 是在 iOS 開發中一個非常重要的角色&#xff0c;他是 view 和 model 的橋梁&#xff0c;通過 UIViewControlle…

第30章 零售與電商AI應用

本章將深入探討人工智能在零售與電商領域的革命性應用。我們將從智能推薦系統、動態定價、庫存管理到創新的虛擬試衣間&#xff0c;全面解析AI如何重塑購物體驗和商業運營效率&#xff0c;并為每個關鍵技術點提供代碼實戰&#xff0c;幫助你掌握將AI應用于真實商業場景的能力。…

QT通過QModbusRtuSerialMaster讀寫電子秤數據實例

一、電子稱常用功能&#xff1a;稱重、清零、去皮&#xff1b;電子秤的通訊方式&#xff1a;Modbus通信、串口通信。二、QT讀寫電子秤軟件界面如下&#xff1a;三、核心代碼如下&#xff1a;.pro項目文件代碼&#xff1a;QT core gui serialbus serialport.h頭文件代碼#…

sqlmap常用命令

ZZHow(ZZHow1024) 一、掃描注入點 1.GET方法&#xff0c;給URL&#xff1a; #探測該url是否存在漏洞 python sqlmap.py -u "http://192.168.10.1/sqli/Less-1/?id1"#如果我們已經知道admin這里是注入點的話&#xff0c;可以在其后面加個*來讓sqlmap對其注入 python …

JVM如何排查OOM

當JVM&#xff08;Java虛擬機&#xff09;出現OOM&#xff08;OutOfMemoryError&#xff09;時&#xff0c;可以按照以下步驟和方法&#xff0c;用于幫助定位和解決JVM中的OOM問題1.查看異常堆棧信息查看異常堆棧信息&#xff08;StackTrace&#xff09;是定位問題的關鍵。OOM異…

存算一體芯片生態評估:從三星PIM到知存科技WTM2101

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;注冊即送-H卡級別算力&#xff0c;80G大顯存&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生更享專屬優惠。 引言&#xff1a;存算一體技術的崛起與意義 在傳統馮諾…

[數據結構] 棧 · Stack

一.棧 stack 1.概念 棧 : 一種特殊的線性表 , 其只允許再固定的一段進行插入和刪除元素操作 進行數據插入和刪除操作的一段稱為 棧頂 ; 另一端稱為棧底棧中的數據元素遵循 先進后出 原則(LIFO)壓棧 : 棧的插入操作叫做 進棧 或 壓棧 或 入棧 , 入數據在棧頂出棧 : 棧的刪除…

MySQL執行過程中如何選擇最佳的執行路徑

本篇文章介紹一個非常核心的數據庫問題。MySQL 選擇最佳執行路徑&#xff08;即“查詢優化”&#xff09;的過程是由其查詢優化器&#xff08;Query Optimizer&#xff09; 完成的。 簡單來說&#xff0c;優化器的目標是&#xff1a;在多種可能的執行方案中&#xff0c;選擇一個…

【設計模式】從游戲角度開始了解設計模式 --- 抽象工廠模式

永遠記住&#xff0c;你的存在是有意義的&#xff0c; 你很重要&#xff0c; 你是被愛著的&#xff0c; 而且你為這個世界帶來了無可取代的東西。 -- 麥克西 《男孩、鼴鼠、狐貍和馬》-- 從零開始了解設計模式抽象工廠模式抽象工廠模式 今天我們一起來探究抽象工廠模式&#x…

tensorflow.js 使用場景

TensorFlow.js (簡稱 TF.js) 是一個利用 WebGL 和 Node.js 在瀏覽器和服務器端進行機器學習模型訓練和部署(推理)的 JavaScript 庫。它的核心價值在于將機器學習的能力帶入了 Web 開發者和 JavaScript 生態的領域。 其主要應用場景可以分為以下幾大類: 一、在瀏覽器中直接進…

詳解mcp以及agen架構設計與實現

文章目錄1.MCP概念2.MCP服務端主要能力3.MCP技術生態4.MCP與Function call區別5.MCP生命周期6.MCP java SDK7.MCP應用場景8.基于springAIollma阿里qianwenmcp設計私有AIAgent應用實現9.AI java項目落地技術選型10.構建AI Agent四大模塊11.LLM(大模型)與MCP之間關系12.A2A、MCP、…

六級第一關——下樓梯

上目錄&#xff1a; 目錄 題目描述 輸入格式 輸出格式 輸入輸出樣例 說明/提示 一、DP的意義以及線性動規簡介 在一個困難的嵌套決策鏈中&#xff0c;決策出最優解。 二、動態規劃性質淺談 三、子序列問題 &#xff08;一&#xff09;一個序列中的最長上升子序列&am…

【Linux基礎】Linux系統配置IP詳解:從入門到精通

目錄 1 Linux網絡配置概述 2 網卡配置文件位置和命名規則 2.1 配置文件位置 2.2 網卡命名規則 2.3 配置文件命名示例 3 網卡配置文件詳解 3.1 主要參數說明 4 Linux系統配置IP步驟 4.1 DHCP動態配置 4.2 靜態IP配置 5 Linux網絡配置流程 5.1 網絡配置流程 5.2 網卡…

C語言sprintf的高效替代方案

C語言的sprintf和snprintf將變量格式化輸出到內存buffer&#xff0c;其功能強大&#xff0c;用起來很方便。但sprintf系列函數的運行效率低下&#xff0c;主要包括四方面的原因&#xff1a;格式字符串解析、變參處理、locale&#xff08;本地化&#xff09;支持和通用&#xff…