Given a binary tree, return all root-to-leaf paths.
For example, given the following binary tree:
1 / \ 2 3 \ 5
All root-to-leaf paths are:
["1->2->5", "1->3"]
這道題給我們一個二叉樹,讓我們返回所有根到葉節點的路徑,跟之前那道Path Sum II很類似,比那道稍微簡單一些,不需要計算路徑和,只需要無腦返回所有的路徑即可,那么思路還是用遞歸來解,博主之前就強調過,玩樹的題目,十有八九都是遞歸,而遞歸的核心就是不停的DFS到葉結點,然后在回溯回去。在遞歸函數中,當我們遇到葉結點的時候,即沒有左右子結點,那么此時一條完整的路徑已經形成了,我們加上當前的葉結點后存入結果res中,然后回溯。注意這里結果res需要reference,而out是不需要引用的,不然回溯回去還要刪除新添加的結點,很麻煩。為了減少判斷空結點的步驟,我們在調用遞歸函數之前都檢驗一下非空即可,代碼而很簡潔,參見如下:
解法一:
class Solution { public: vector<string> binaryTreePaths(TreeNode* root) { vector<string> res; if (root) helper(root, "", res); return res; } void helper(TreeNode* node, string out, vector<string>& res) { if (!node->left && !node->right) res.push_back(out + to_string(node->val)); if (node->left) helper(node->left, out + to_string(node->val) + "->", res); if (node->right) helper(node->right, out + to_string(node->val) + "->", res); } };
下面再來看一種遞歸的方法,這個方法直接在一個函數中完成遞歸調用,不需要另寫一個helper函數,核心思想和上面沒有區別,參見代碼如下:
解法二:
class Solution { public: vector<string> binaryTreePaths(TreeNode* root) { if (!root) return {}; if (!root->left && !root->right) return {to_string(root->val)}; vector<string> left = binaryTreePaths(root->left); vector<string> right = binaryTreePaths(root->right); left.insert(left.end(), right.begin(), right.end()); for (auto &a : left) { a = to_string(root->val) + "->" + a; } return left; } };
還是遞歸寫法,從論壇中扒下來的解法,核心思路都一樣啦,寫法各有不同而已,參見代碼如下:
解法三:
class Solution { public: vector<string> binaryTreePaths(TreeNode* root) { if (!root) return {}; if (!root->left && !root->right) return {to_string(root->val)}; vector<string> res; for (string str : binaryTreePaths(root->left)) { res.push_back(to_string(root->val) + "->" + str); } for (string str : binaryTreePaths(root->right)) { res.push_back(to_string(root->val) + "->" + str); } return res; } };
類似題目:
參考資料: