Day18
513.找树左下角的值
递归,按前中后序遍历都可以。只要先遍历左子树就行。
前序
class Solution {
public:
int result;
int treedepth;
void getdepth(TreeNode* node,int depth){
if(node==NULL) return;
if(depth>treedepth){
treedepth=depth;
result=node->val;
}
if(node->left){
depth++;
getdepth(node->left,depth);
depth--;
}
if(node->right){
depth++;
getdepth(node->right,depth);
depth--;
}
return;
}
int findBottomLeftValue(TreeNode* root) {
int depth=1;
getdepth(root,depth);
return result;
}
};
层序遍历
需要注意的是如果没说明使用了deque定义队列,那么不能使用push_back();
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
que.push(root);
int val;
while(!que.empty()){
int size=que.size();
TreeNode* node=que.front();
que.pop();
val=node->val;
if(node->left){
que.push(node->left);
}
if(node->right){
que.push(node->right);
}
for(int i=0;i<size-1;i++){
TreeNode* cur=que.front();
que.pop();
if(cur->left)que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return val;
}
};
112. 路径总和
首先是我自己考虑的递归方法,判断是否相等,相等返回.但是存在一个问题,当找到符合要求的结果后不会马上退出递归。有一种解法
return isSame(node->left, sum, targetSum) || isSame(node->right, sum, targetSum);
写成这种 || 的形式就可以允许短路行为。
这里面主要是返回值的问题,
1.如果需要遍历整个树,而且返回值不需要处理,比如在函数外定义的result这种,就不需要返回值。
2.如果需要处理返回值,那么就需要根据需要返回值
3.如果不需要遍历整个树,找到结果就可以返回这种,那么也需要返回值,就像本题,找到一种路径就可以退出递归循环了。所以考虑使用bool,其实bool也是一种返回值,所以只需要判断左右子树是否符合要求就可以了。
这也是二叉树常用的一种递归思路:左右子树是否符合
class Solution {
public:
bool isSame(TreeNode* node,int sum,int targetSum){
sum+=node->val;
if(sum == targetSum && node->left==NULL && node->right==NULL){
return true;
}
bool left;
bool right;
if(node->left){
left=isSame(node->left,sum,targetSum);
}
if(node->right){
right=isSame(node->right,sum,targetSum);
}
return left || right;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==NULL) return false;
return isSame(root,0,targetSum);
}
};
下面是代码随想录的,区别就在于他用target减去目标值。然后把if判断结果也是true与false特性考虑进去,只要出现true,也会一级级退出循环,使用if也可以允许短路行为。
class Solution {
public:
bool isSame(TreeNode* node,int sum){
sum-=node->val;
if(node->left==NULL&& node->right==NULL && sum==0){
return true;
}
if(node->left){
if(isSame(node->left,sum)) return true;
}
if(node->right){
if(isSame(node->right,sum)) return true;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==NULL) return false;
int sum=targetSum;
return isSame(root,sum);
}
};
迭代法
auto
不能用于直接调用构造函数
pair的用法
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
stack<pair<TreeNode*,int>> st;
if(root==NULL) return false;
st.push(pair<TreeNode*,int>(root,root->val));
while(!st.empty()){
auto node=st.top();
st.pop();
if(node.first->left==NULL&&node.first->right==NULL&&node.second==targetSum){
return true;
}
if(node.first->left){
st.push(pair<TreeNode*,int>(node.first->left,node.second+node.first->left->val));
}
if(node.first->right){
st.push(pair<TreeNode*,int>(node.first->right,node.second+node.first->right->val));
}
}
return false;
}
};
113.路径总和ii
使用迭代法:难点在于如何存储路径,同时又判断是否相等。
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
stack<pair<TreeNode*,int>> st;
vector<vector<int>> result;
stack<vector<int>> st2;
vector<int> vec;
if(root==NULL){return result;}
st.push({root,root->val});
vec.push_back(root->val);
st2.push(vec);
while(!st.empty()){
auto node=st.top();
st.pop();
vector<int> node2=st2.top();//到该节点的路径
st2.pop();
if(node.first->left==NULL && node.first->right==NULL && node.second==targetSum){
result.push_back(node2);
}
if(node.first->left){
st.push(pair<TreeNode*,int>(node.first->left,node.second+node.first->left->val));
vector<int> node3=node2;
node3.push_back(node.first->left->val);
st2.push(node3);
}
if(node.first->right){
st.push(pair<TreeNode*,int>(node.first->right,node.second+node.first->right->val));
node2.push_back(node.first->right->val);
st2.push(node2);
}
}
return result;
}
};
递归法:
跟之前的其实差不多思路,区别在于要遍历全树以及如何存储路径。
class Solution {
public:
vector<vector<int>> result;
vector<int> vec;
void isSame(TreeNode* node,int sum){
vec.push_back(node->val);
sum-=node->val;
if(node->left==NULL && node->right==NULL && sum==0){
result.push_back(vec);
vec.pop_back();
return;
}
if(node->left){
isSame(node->left,sum);
}
if(node->right){
isSame(node->right,sum);
}
vec.pop_back();
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root==NULL) return result;
int sum=targetSum;
isSame(root,sum);
return result;
}
};
106.从中序与后序遍历序列构造二叉树
思路不算很难,但是写起来小问题很多,主要是分割数组的边界问题
在定义一个vector时,.end()指向的那个不在容器内,定义也是一样
vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
这里面最后一个元素不在容器内。
下面是在原本给出的容器内进行操作:
class Solution {
public:
TreeNode* travelsal(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);
int delimiterIndex;
for(delimiterIndex=inorderbegin;delimiterIndex<inorderend;delimiterIndex++){
if(inorder[delimiterIndex]==rootvalue) break;
}
int leftinorderbegin=inorderbegin;
int leftinorderend=delimiterIndex;
int rightinorderbegin=delimiterIndex+1;
int rightinorderend=inorderend;
int leftpostorderbegin=postorderbegin;
int leftpostorderend=postorderbegin+delimiterIndex-inorderbegin;
int rightpostorderbegin=postorderbegin+delimiterIndex-inorderbegin;
int rightpostorderend=postorderend-1;
root->left=travelsal(inorder,leftinorderbegin,leftinorderend,postorder,leftpostorderbegin,leftpostorderend);
root->right=travelsal(inorder,rightinorderbegin,rightinorderend,postorder,rightpostorderbegin,rightpostorderend);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size()==0) return NULL;
return travelsal(inorder,0,inorder.size(),postorder,0,postorder.size());
}
};
105.从前序与中序遍历序列构造二叉树
跟上面那题思路差不多,只不过从找最后一个节点变成了找第一个节点。
下面是使用vector的代码
class Solution {
public:
TreeNode* travelsal(vector<int>& preorder,vector<int>& inorder){
if(inorder.size()==0) return NULL;
int rootValue=preorder[0];
TreeNode* root=new TreeNode(rootValue);
int delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++){
if(inorder[delimiterIndex]==rootValue) break;
}
vector<int> leftin(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightin(inorder.begin()+delimiterIndex+1,inorder.end());
vector<int> leftpre(preorder.begin()+1,preorder.begin()+leftin.size()+1);
vector<int> rightpre(preorder.begin()+leftin.size()+1,preorder.end());
root->left=travelsal(leftpre,leftin);
root->right=travelsal(rightpre,rightin);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0) return NULL;
return travelsal(preorder,inorder);
}
};
使用下标索引
class Solution {
public:
TreeNode* travelsal(vector<int>& preorder,int preorderbegin,int preorderend,vector<int>& inorder,int inorderbegin,int inorderend){
if(preorderbegin==preorderend) return NULL;
int rootValue=preorder[preorderbegin];
TreeNode* root=new TreeNode(rootValue);
int delimiterIndex;
for(delimiterIndex=inorderbegin;delimiterIndex<inorderend;delimiterIndex++){
if(inorder[delimiterIndex]==rootValue) break;
}
int leftinorderbegin=inorderbegin;
int leftinorderend=delimiterIndex;
int rightinorderbegin=delimiterIndex+1;
int rightinorderend=inorderend;
int leftpreorderbegin=preorderbegin+1;
int leftpreorderend=preorderbegin+1+delimiterIndex-inorderbegin;
int rightpreorderbegin=preorderbegin+1+delimiterIndex-inorderbegin;
int rightpreorderend=preorderend;
root->left=travelsal(preorder,leftpreorderbegin,leftpreorderend,inorder,leftinorderbegin,leftinorderend);
root->right=travelsal(preorder,rightpreorderbegin,rightpreorderend,inorder,rightinorderbegin,rightinorderend);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0){
return NULL;
}
return travelsal(preorder,0,preorder.size(),inorder,0,inorder.size());
}
};