day18
代码随想录
2023.12.16
1. 513找树左下角的值
这道题很直观的就是想到层序遍历,最后一层的第一个节点值就是我们需要的,而且很偷懒的是,不用判断是不是最后一层,每一层第一个节点值都保存,会覆盖,最后的值就是我们要的。
最后看代码随想录还讲了递归写法,就是在递归时加了个深度变量,最深且是左节点的就是我们要找的值,挺麻烦的,不细说了
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);int result;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;}
};
2. 112路经总和
这道题跟前几天做的一道所有路径很相似,那道题是将所有路径要要求打印出来,这是求和,思路是一样的,只是在最终路径处理上不同,这道题在叶子节点是将path的值全部相加,如果==targetsum,则返回true即可。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:bool hasPathSum(TreeNode* root, int targetSum) {vector<int> path;if(root==NULL) return false;return travel(root, path, targetSum);}bool travel(TreeNode*node, vector<int>& path, const int target){path.push_back(node->val);bool lefti=false;bool righti=false;if(node->left){lefti=travel(node->left, path, target);path.pop_back();}if(node->right){righti=travel(node->right, path, target);path.pop_back();}if(node->left==NULL && node->right==NULL){int sum=0;for(int i=0;i<path.size();i++){sum +=path[i];}cout<<sum<<endl;if(sum==target) return true;}return (lefti||righti);}
};
3. 106从中序和后续遍历结果构造二叉树
这道题是这道时间遇到的最难一题了。拿到后有些没有头绪,手写结果很简单,没什么那难度,但代码实现就不知道怎么写了,看了代码随想录文字讲解,悟了一点;
首先明确,是要递归处理的,每次传入两个数组,构造子树。重点是就是函数的实现。每次递归都是以后序遍历的最后一个元素为重点的,该元素就是本次递归的根节点,以该节点为中心,将中序遍历划分为两个部分,就是下次递归的左右子树的中序遍历结果。所以中序遍历很好切割,思路就是,根据后序遍历找到中心点,再在中序遍历找到中心点的位置,以该位置分割中序遍历数组;那么,后续遍历怎么分割?后续遍历没有中序遍历那么明显的分割点,但要知道,中序遍历和后序遍历的数组大小是相等的,所以知道中序遍历分割结果,可以根据该结果去按大小分割后续遍历,但要注意顺序。最终得到两个中序遍历,两个后序遍历,在分别匹配传给递归函数构造本次递归函数的根节点的左右子树。即可
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* traversal (vector<int>& inorder, vector<int>& postorder) {if (postorder.size() == 0) return NULL;// 后序遍历数组最后一个元素,就是当前的中间节点int rootValue = postorder[postorder.size() - 1];TreeNode* root = new TreeNode(rootValue);// 叶子节点if (postorder.size() == 1) return root;// 找到中序遍历的切割点int delimiterIndex;for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break;}// 切割中序数组// 左闭右开区间:[0, delimiterIndex)vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);// [delimiterIndex + 1, end)vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );// postorder 舍弃末尾元素postorder.resize(postorder.size() - 1);// 切割后序数组// 依然左闭右开,注意这里使用了左中序数组大小作为切割点// [0, leftInorder.size)vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());// [leftInorder.size(), end)vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());root->left = traversal(leftInorder, leftPostorder);root->right = traversal(rightInorder, rightPostorder);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if (inorder.size() == 0 || postorder.size() == 0) return NULL;return traversal(inorder, postorder);}
};