找树左下角的值
定义:二叉树中最后一行最靠左侧的值。
前序,中序,后序遍历都是先遍历左然后遍历右。
因为优先遍历左节点,所以递归中因为深度增加更新result的时候,更新的值是当前深度最左侧的值,到最后就得到了最后一行最靠左的节点。
注意:其中也有回溯,depth++; traversal(root->left,depth); depth–;这里,为什么用函数处理完之后depth要–?因为在处理完左节点的深度后,要减掉左节点的深度,然后再处理右节点的深度。
下面是C++, JAVA, Python的代码。
/*** 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 maxDepth = INT_MIN;//int中的最小值int result;//记录节点的值void traversal(TreeNode* root, int depth){if(root->left == NULL && root->right == NULL){if(depth > maxDepth){maxDepth = depth;result = root->val;//如果深度增加就更新result保存的节点的值,因为遍历顺序是坐在右的前面所以能让result更新的一定是当前深度下的最左边的节点}}//然后处理左节点的值if(root->left){depth++;traversal(root->left, depth);depth--;//回溯}//这三行就相当于traversal(root->left, depth+1)//做了++操作但是没有改变depth的值if(root->right){depth++;traversal(root->right, depth);depth--;}}int findBottomLeftValue(TreeNode* root) {int depth = 0;traversal(root, depth);return result;}
};
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {private int maxDepth = -1;private int result;void traversal(TreeNode root, int depth){if(root.left == null && root.right==null){//碰到叶子节点了来比较当前叶子节点的深度和最大深度if(depth > maxDepth){maxDepth = depth;result = root.val;}}//处理左节点if(root.left!=null){depth++;traversal(root.left, depth);depth--;//这三行相当于traversal(root.left, depth+1)}//处理右节点if(root.right!=null){depth++;traversal(root.right, depth);depth--;//这三行相当于traversal(root.right, depth+1)}}public int findBottomLeftValue(TreeNode root) {int depth = 0;traversal(root, depth);return result;}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):def traversal(self, root, depth):if root.left==None and root.right==None:if depth > self.maxDepth:#如果当前深度比最大深度大,更新result的值self.maxDepth = depthself.result = root.valif root.left!=None:depth+=1self.traversal(root.left, depth)depth-=1if root.right!=None:depth+=1self.traversal(root.right, depth)depth-=1def findBottomLeftValue(self, root):""":type root: Optional[TreeNode]:rtype: int"""self.maxDepth = -1self.result = Nonedepth = 0self.traversal(root, depth)return self.result
参考文章
- https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html
路径总和
我们在递归外面用目标值减去根节点的值得到新的目标值,这样之后不必处理中也就是节点本身,而是处理节点的左右子节点。前中后序都一样(因为没有对中进行操作,只对左右进行操作)。
- 确定递归函数的参数和返回值:参数node和 count,输出是bool类型。如果它遍历的一条子路径符合要求就一层一层向上返回true。
- 确定终止条件:因为对左右子节点进行操作,所以要避免左右子节点为空,如果为空,count为0符合要求返回True,如果左右节点为空,count不为0不符合要求,返回False。
- 确定单层递归的逻辑:count减去当前的left/right节点,然后放到递归函数中判断。回溯的时候count+上当前的left/right节点。
下面是C++,JAVA和Python代码。
其中也用到了回溯,再理解一遍回溯思想。在处理左右节点的时候的函数。
count-=node->left->val;
if(traversal(node->left, count)) return true;
count += node->left->val;
我看弹幕上有人说:发现这条路径最后count不是0不符合条件的情况下,需要找到别的路径,这就需要退回去找。
/*** 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) {if(root){int count = targetSum-root->val;return traversal(root, count);}return false;}bool traversal(TreeNode* node, int count){if(node->left==NULL && node->right==NULL && count==0) return true;if(node->left==NULL && node->right==NULL && count!=0) return false;if(node->left){//要判断左孩子不为空否则递归左孩子的时候会出现空指针异常count-=node->left->val;if(traversal(node->left, count)) return true;count += node->left->val;}if(node->right){count-=node->right->val;if(traversal(node->right, count)) return true;count += node->right->val;}return false;}
};
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {boolean traversal(TreeNode node, int count){if(node.left==null && node.right==null && count==0) return true;if(node.left==null && node.right==null && count!=0) return false;if(node.left!=null){count-=node.left.val;if(traversal(node.left, count)) return true;//函数中最开始进行判断count+=node.left.val;//回溯}if(node.right!=null){count-=node.right.val;if(traversal(node.right, count)) return true;count+=node.right.val;}return false;}public boolean hasPathSum(TreeNode root, int targetSum) {if(root!=null){int count = targetSum-root.val;return traversal(root, count);}return false;}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):def hasPathSum(self, root, targetSum):""":type root: Optional[TreeNode]:type targetSum: int:rtype: bool"""if(root!=None):count=targetSum-root.valreturn self.traversal(root, count)return Falsedef traversal(self, node, count):if node.left==None and node.right==None and count==0:return Trueif node.left==None and node.right==None and count!=0:return False#说明这条路径不是if(node.left != None):count -= node.left.valif(self.traversal(node.left, count)):return Truecount += node.left.valif(node.right != None):count -= node.right.valif(self.traversal(node.right, count)):return Truecount += node.right.valreturn False
路径之和Ⅱ
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
与上一个相比要定义vector<vector> result;存储所有的路径,vector path;存储当前路径。
下面是C++,JAVA和Python代码。
/*** 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 {
private:vector<vector<int>> result;vector<int> path;//递归函数不需要返回值,因为我们要遍历整个树void traversal(TreeNode* cur, int count){if(!cur->left && !cur->right && count == 0){//遇到了叶子节点,而且找到了和为targetSum的路径result.push_back(path);return;}if(!cur->left && !cur->right) return; //如果遇到叶子节点,没有合适的路径就直接返回if(cur->left){//左,防止遍历空节点path.push_back(cur->left->val);//从后面加入count -= cur->left->val;traversal(cur->left, count);//递归count += cur->left->val;//下面两个都是回溯,就是递归到这个节点和出这个节点的两种情况下环境不变path.pop_back();//从后面弹出}if(cur->right){//左,防止遍历空节点path.push_back(cur->right->val);//从后面加入count -= cur->right->val;traversal(cur->right, count);//递归count += cur->right->val;//下面两个都是回溯,就是递归到这个节点和出这个节点的两种情况下环境不变path.pop_back();//从后面弹出}return;}
public:vector<vector<int>> pathSum(TreeNode* root, int targetSum) {result.clear();path.clear();if(root==NULL) return result;path.push_back(root->val);//把根节点放到路径traversal(root, targetSum - root->val);return result;}
};
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<List<Integer>> pathSum(TreeNode root, int targetSum) {List<List<Integer>> result = new ArrayList<>();if (root == null) return result; // 非空判断Deque<Integer> path = new LinkedList<>(); // 使用Dequepath.add(root.val);traversal(root, targetSum - root.val, result, path);return result;}public void traversal(TreeNode root, int count, List<List<Integer>> result, Deque<Integer> path) {if (root.left == null && root.right == null && count == 0) {result.add(new ArrayList<>(path));return;}if (root.left == null && root.right == null) return; // 这条路径不符合要求if (root.left != null) { // 左子树path.addLast(root.left.val);count -= root.left.val;traversal(root.left, count, result, path);count += root.left.val;path.pollLast();}if (root.right != null) { // 右子树path.addLast(root.right.val);count -= root.right.val;traversal(root.right, count, result, path);count += root.right.val;path.pollLast();}}
}
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):def __init__(self):self.result = []self.path = []def traversal(self, cur, count):if not cur.left and not cur.right and count == 0:#遇到了叶子节点而且找到了和为目标值的路径self.result.append(self.path[:])return if not cur.left and not cur.right:#遇到了叶子节点但是路径不符合条件returnif cur.left:#左 空节点不遍历self.path.append(cur.left.val)count-=cur.left.valself.traversal(cur.left, count)count += cur.left.valself.path.pop() #回溯if cur.right: #右 空节点不遍历self.path.append(cur.right.val)count -= cur.right.valself.traversal(cur.right, count) #递归count += cur.right.val #回溯self.path.pop() #回溯returndef pathSum(self, root, targetSum):""":type root: Optional[TreeNode]:type targetSum: int:rtype: List[List[int]]"""if not root:return self.resultself.path.append(root.val)self.traversal(root, targetSum - root.val)return self.result
参考文章
- https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html
从中序与后序遍历序列构造二叉树
下面是C++代码。
主要的步骤有6个:
- 后序数组为0,说明是空节点。
- 后续数组最后一个元素为节点元素。
- 寻找中序数组位置找切割点。
- 切割中序数组。
- 切割后序数组。
- 递归处理左区间和右区间。
/*** 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:
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] == root->val) break;}//切割中序数组//左中序区间左闭右开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; // 终止位置是 需要加上 中序区间的大小size// 右后序区间,左闭右开[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()); }
};
参考文章
- https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html