二叉樹與深度優先遍歷
資料結構與演算法中利用深度優先遍歷(DFS)藉助二叉樹問題。
二叉樹結點定義:
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
Sum Root to Leaf Numbers
題目描述:Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers.
For example,
1
/ \
2 3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Return the sum = 12 + 13 = 25.
//法一:棧實現
int sumNumbers(TreeNode* root)
{
if(!root) return 0;
int sum = 0;
stack<TreeNode*> toVisit;
toVisit.push(root);
while (!toVisit.empty())
{
TreeNode* cur = toVisit.top();
toVisit.pop();
if(cur->right)
{
cur->right->val = cur->val * 10 + cur->right->val;
toVisit.push(cur->right);
}
if(cur->left)
{
cur->left->val = cur->val * 10 + cur->left->val;
toVisit.push(cur->left);
}
if(!cur->left && !cur->right)
{
sum += cur->val;
}
}
return sum;
}
//法二:遞迴實現
class Solution {
public:
int sumNumbers(TreeNode* root) {
return sum(root, 0);
}
private:
int sum(TreeNode* node, int s)
{
if(!node) return 0;
if(!node->left && !node->right)
return s * 10 + node->val;
return sum(node->left, s * 10 + node->val) + sum(node->right, s * 10 + node->val);
}
};
Path Sum
題目描述:Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.LeetCode
For example: Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
//深度優先遍歷,迭代(藉助棧)實現
bool hasPathSum(TreeNode* root, int sum)
{
if(!root) return false;
stack<TreeNode*> toVisit;
toVisit.push(root);
int pathSum = 0;
while(!toVisit.empty())
{
TreeNode* cur = toVisit.top();
toVisit.pop();
if(cur->right)
{
cur->right->val += cur->val;
toVisit.push(cur->right);
}
if(cur->left)
{
cur->left->val += cur->val;
toVisit.push(cur->left);
}
if(!cur->left && !cur->right)
{
if(cur->val == sum)
return true;
}
}
return false;
}
//深度優先遍歷,遞迴實現
bool hasPathSum(TreeNode* root, int sum)
{
if(!root) return false;
if(!root->left && !root->right && root->val == sum) return true;
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
}
Path Sum II
題目描述:Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.LeetCode
For example: Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
return
[
[5,4,11,2],
[5,8,4,5]
]
//深度優先遍歷 + 回溯法
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> result;
if(!root) return result;
vector<int> path;
traverse(root, sum, result, path);
return result;
}
private:
void traverse(TreeNode* node, int sum, vector<vector<int>>& result, vector<int>& path)
{
if(node == NULL) return;
path.push_back(node->val);
if(!node->left && !node->right && sum == node->val)
result.push_back(path);
traverse(node->left, sum - node->val, result, path);
traverse(node->right, sum - node->val, result, path);
path.pop_back();
}
//與上面等價
void traverse(TreeNode* node, int sum, vector<vector<int>>& result, vector<int>& path)
{
if(node == NULL) return;
path.push_back(node->val);
if(!node->left && !node->right && sum == node->val)
{
result.push_back(path);
path.pop_back();
return;
}
traverse(node->left, sum - node->val, result, path);
traverse(node->right, sum - node->val, result, path);
path.pop_back();
}
};
Binary Tree Maximum Path Sum
題目描述:Given a binary tree, find the maximum path sum. For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.LeetCode
分析:要求二叉樹中任意兩個結點之間最大路徑和,而不是從根結點出發到某一子結點的最大路徑和。可採用深度優先遍歷求解,只不過遞迴函式的返回值不是要求的最大和(最大和通過一個全域性變數或者引用引數來同步更新),而是結點自身為根結點時到其子結點的最大路徑,該值用於提供給其父結點計算最長路徑(當其父節點為根結點時,下面的子結點只能是單向的)。簡單來說,一個結點的最大路徑和是其左子樹路徑和 + 右子樹路徑和 + 當前節點值,而返回值則是當前結點值加上左子樹路徑和與右子樹路徑和的較大值。考慮負數的影響,加入與0的比較。
int maxPathSum(TreeNode* root)
{
int maxVal = INT_MIN;
maxPathDown(maxVal, root);
return maxVal;
}
int maxPathDown(int& maxVal, TreeNode* node)
{
if(!node) return 0;
int left = max(0, maxPathDown(maxVal, node->left)); //與0比較考慮了負數的影響
int right = max(0, maxPathDown(maxVal, node->right));
maxVal = max(maxVal, left + right + node->val);
return max(left, right) + node->val;
}