其实dfs的精髓就在于递归函数的参数设置和这些参数在单次递归中的操作,注意部分参数的设立是为了方便递归的进行,这些参数是随着函数的逐步递归而不断变化的
Leetcode 513. 找树左下角的值
链接:513. 找树左下角的值
thought:
- 最小值INT_MIN,最大值INT_MAX
- DFS思路:找出该二叉树的 最底层 最左边 节点的值,最左边容易找到,难点在于如何找到最左边的同时是最底层,DFS的想法是设置一个全局变量depth来实时的记录此时遍历位置的深度,当
depth > maxDepth
时更新深度,同时更新全局变量result的值为root->val
- BFS思路:每到新的一行用变量result记录
完整C++代码如下:
//DFS
class Solution {
public:
int maxdepth = INT_MIN;
int result;
int findBottomLeftValue(TreeNode* root) {
dfs_traversal(root, 1);
return result;
}
void dfs_traversal(TreeNode* root, int depth) {
if (!root)
return;
if (depth > maxdepth) {
maxdepth = depth;
result = root->val;
}
if (root->left) {
dfs_traversal(root->left, depth + 1);
}
if (root->right) {
dfs_traversal(root->right, depth + 1);
}
}
};
//BFS
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
int result = 0;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
//记录最后一行第一个元素
if (i == 0) result = node->val;
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
Leetcode 112. 路径总和
链接:112. 路径总和
thought:
- DFS:设置全局变量ifNum用来判断是否有路径总和与targetNum相同,当遍历到底层时将当前num与targetNum比较,若相同将ifNum置为true
完整C++代码如下:
//DFS
class Solution {
public:
bool ifNum = false;
bool hasPathSum(TreeNode* root, int targetSum) {
traversal_(root, targetSum, 0);
return ifNum;
}
void traversal_(TreeNode* root, int targetSum, int num) {
if (!root)
return;
num += root->val;
if (!root->left && !root->right) {
if (targetSum == num) {
ifNum = true;
}
}
if (root->left)
traversal_(root->left, targetSum, num);
if (root->right)
traversal_(root->right, targetSum, num);
}
};
Leetcode 113. 路径总和 II
链接:113. 路径总和 II
thought:
- DFS,code思路很直观,就是前序遍历
完整C++代码如下:
class Solution {
public:
vector<vector<int>> res;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<int> cur;
traversal_(root, targetSum, cur, 0);
return res;
}
void traversal_(TreeNode* root, int targetSum, vector<int> cur,
int cur_sum) {
if (!root)
return;
cur_sum += root->val;
cur.push_back(root->val);
if (!root->left && !root->right) {
if (cur_sum == targetSum) {
res.push_back(cur);
}
}
if (root->left)
traversal_(root->left, targetSum, cur, cur_sum);
if (root->right)
traversal_(root->right, targetSum, cur, cur_sum);
}
};
Leetcode 106. 从中序与后序遍历序列构造二叉树
thought:
- 判断后序遍历数组大小是否为0,为0直接return NULL
- 通过后序遍历数组找到根节点
- 从而找到中序切割点
- 切中序(可用下标代替完成)
- 设后序size减1
- 切后序
- 下一层递归
完整C++代码如下:
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (postorder.size() == 0)
return NULL;
// 后序遍历数组的最后一个元素为根节点
int rootVal = postorder[postorder.size() - 1];
TreeNode* root = new TreeNode(rootVal);
if (postorder.size() == 1) {
return root;
}
// 找到中序遍历的切割点
int delimiterIndex; // delimiter意为分隔符
for (delimiterIndex = 0; delimiterIndex < inorder.size();
delimiterIndex++) {
if (inorder[delimiterIndex] == rootVal)
break;
}
//切中序
//[0, delimiterIndex)
vector<int> leftInorder(inorder.begin(),
inorder.begin() + delimiterIndex);
//[delimiterIndex + 1, end)
vector<int> rightInorder(
inorder.begin() + delimiterIndex + 1,
inorder.end()); // 如果右为空,不会报错,会指向空的end
//后序数组重设大小
postorder.resize(postorder.size() - 1);
//切后序
// [0, leftInorder.size())
vector<int> leftPostorder(postorder.begin(),
postorder.begin() + leftInorder.size());
// [rightPostorder.size(), end)
vector<int> rightPostorder(postorder.begin() + leftInorder.size(),
postorder.end());
root->left = buildTree(leftInorder, leftPostorder);
root->right = buildTree(rightInorder, rightPostorder);
return root;
}
};
class Solution {
private:
TreeNode* traversal(vector<int>& inorder, int inorderBegin, int inorderEnd,
vector<int>& postorder, int postorderBegin,
int postorderEnd) {
if (postorderBegin == postorderEnd)
return NULL;
//找到根节点,设立二叉树树
int rootValue = postorder[postorderEnd - 1];
TreeNode* root = new TreeNode(rootValue);
if (postorderEnd - postorderBegin == 1)
return root;
int delimiterIndex;
for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd;
delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue)
break;
}
// 切中序
// 左中序区间,左闭右开[leftInorderBegin, leftInorderEnd)
int leftInorderBegin = inorderBegin;
int leftInorderEnd = delimiterIndex;
// 右中序区间,左闭右开[rightInorderBegin, rightInorderEnd)
int rightInorderBegin = delimiterIndex + 1;
int rightInorderEnd = inorderEnd;
// 切后序,注意下面后序遍历数组排除最后一个元素操作
// 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
int leftPostorderBegin = postorderBegin;
int leftPostorderEnd =
postorderBegin + delimiterIndex -
inorderBegin;
// 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
int rightPostorderBegin =
postorderBegin + (delimiterIndex - inorderBegin);
int rightPostorderEnd =
postorderEnd - 1; // 排除最后一个元素,已经作为节点了
root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,
postorder, leftPostorderBegin, leftPostorderEnd);
root->right =
traversal(inorder, rightInorderBegin, rightInorderEnd, postorder,
rightPostorderBegin, rightPostorderEnd);
return root;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0)
return NULL;
// 左闭右开的原则
return traversal(inorder, 0, inorder.size(), postorder, 0,
postorder.size());
}
};