路徑總和II——深度優先於廣度優先的實踐
阿新 • • 發佈:2021-01-13
技術標籤:LeetCode
一、題目
給定一個二叉樹和一個目標和,找到所有從根節點到葉子節點路徑總和等於給定目標和的路徑。說明: 葉子節點是指沒有子節點的節點。
示例:給定如下二叉樹,以及目標和 sum = 22,
二、題解
注意到本題的要求是,找到所有滿足從「根節點」到某個「葉子節點」經過的路徑上的節點之和等於目標和的路徑。核心思想是對樹進行一次遍歷,在遍歷時記錄從根節點到當前節點的路徑和,以防止重複計算。
2.1深度優先搜尋
我們可以採用深度優先搜尋的方式,列舉每一條從根節點到葉子節點的路徑。當我們遍歷到葉子節點,且此時路徑和恰為目標和時,我們就找到了一條滿足條件的路徑。
class Solution { public: vector<vector<int>> ret; vector<int> path; void dfs(TreeNode* root, int sum) { if (root == nullptr) { return; } path.emplace_back(root->val); sum -= root->val; if (root->left == nullptr && root->right == nullptr && sum == 0) { ret.emplace_back(path); } dfs(root->left, sum); dfs(root->right, sum); path.pop_back(); } vector<vector<int>> pathSum(TreeNode* root, int sum) { dfs(root, sum); return ret; } };
2.2廣度優先搜尋
我們也可以採用廣度優先搜尋的方式,遍歷這棵樹。當我們遍歷到葉子節點,且此時路徑和恰為目標和時,我們就找到了一條滿足條件的路徑。
為了節省空間,我們使用雜湊表記錄樹中的每一個節點的父節點。每次找到一個滿足條件的節點,我們就從該節點出發不斷向父節點迭代,即可還原出從根節點到當前節點的路徑。
class Solution { public: vector<vector<int>> ret; unordered_map<TreeNode*, TreeNode*> parent; void getPath(TreeNode* node) { vector<int> tmp; while (node != nullptr) { tmp.emplace_back(node->val); node = parent[node]; } reverse(tmp.begin(), tmp.end()); ret.emplace_back(tmp); } vector<vector<int>> pathSum(TreeNode* root, int sum) { if (root == nullptr) { return ret; } queue<TreeNode*> que_node; queue<int> que_sum; que_node.emplace(root); que_sum.emplace(0); while (!que_node.empty()) { TreeNode* node = que_node.front(); que_node.pop(); int rec = que_sum.front() + node->val; que_sum.pop(); if (node->left == nullptr && node->right == nullptr) { if (rec == sum) { getPath(node); } } else { if (node->left != nullptr) { parent[node->left] = node; que_node.emplace(node->left); que_sum.emplace(rec); } if (node->right != nullptr) { parent[node->right] = node; que_node.emplace(node->right); que_sum.emplace(rec); } } } return ret; } };
參考:
https://leetcode-cn.com/problems/path-sum-ii/solution/lu-jing-zong-he-ii-by-leetcode-solution/