力扣整理版七:二叉树(待更新)
满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。深度为k,有2^k-1个节点的二叉树。
完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h从1开始),则该层包含 1~ 2^(h-1) 个节点。
二叉搜索树:左<根<右。
平衡二叉搜索树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
-----------------------------
(1) 144 二叉树的前序遍历
(2) 145 二叉树的后序遍历
(3) 94 二叉树的中序遍历
(4) 102 二叉树的层序遍历
(5) 107 二叉树的层序遍历2
(6) 199 二叉树的右视图
(7) 637 二叉树的层平均值
(8) 429 N叉树的层序遍历
(9) 515 在每个树行中找最大值
(10) 116 填充每个节点的下一个右侧节点指针
(11) 117 填充2(18) 404 左叶子之和
(12) 104 二叉树的最大深度
(13) 111 二叉树的最小深度
(14) 226 翻转二叉树
(15) 101 对称二叉树
(16) 222 完全二叉树的节点个数
(17) 257 二叉树的所有路径
(18) 404 左叶子之和
-----------------------------
一、二叉树的递归遍历
1、确定递归函数的参数和返回值;2、确定终止条件;3、确定单层递归的逻辑;
144. 二叉树的前序遍历 - 力扣(LeetCode)
1、前序遍历
------------- python -------------
class Solution:def preorderTraversal(self, root: TreeNode) -> List[int]:res = []def dfs(node):if node is None:returnres.append(node.val)dfs(node.left)dfs(node.right)dfs(root)return res
------------- c++ -------------
class Solution {
public:void traversal(TreeNode* cur, vector<int>& vec) {if (cur == NULL) return;vec.push_back(cur->val); // 中traversal(cur->left, vec); // 左traversal(cur->right, vec); // 右}vector<int> preorderTraversal(TreeNode* root) {vector<int> result;traversal(root, result);return result;}
};
2、中序遍历
94. 二叉树的中序遍历 - 力扣(LeetCode)
------------- python -------------
# 中序遍历-递归-LC94_二叉树的中序遍历
class Solution:def inorderTraversal(self, root: TreeNode) -> List[int]:res = []def dfs(node):if node is None:returndfs(node.left)res.append(node.val)dfs(node.right)dfs(root)return res
------------- c++ -------------
void traversal(TreeNode* cur, vector<int>& vec) {if (cur == NULL) return;traversal(cur->left, vec); // 左vec.push_back(cur->val); // 中traversal(cur->right, vec); // 右
}
3、后序遍历
145. 二叉树的后序遍历 - 力扣(LeetCode)
------------- python -------------
class Solution:def postorderTraversal(self, root: TreeNode) -> List[int]:res = []def dfs(node):if node is None:returndfs(node.left)dfs(node.right)res.append(node.val)dfs(root)return res
------------- c++ -------------
void traversal(TreeNode* cur, vector<int>& vec) {if (cur == NULL) return;traversal(cur->left, vec); // 左traversal(cur->right, vec); // 右vec.push_back(cur->val); // 中
}
二、二叉树的迭代遍历
1、前序遍历
144. 二叉树的前序遍历 - 力扣(LeetCode)
------------- python -------------
class Solution:def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:if not root:return []stack=[]res=[]while stack or root:if root:res.append(root.val)stack.append(root)root=root.leftelse:tem=stack.pop()root=tem.rightreturn res
------------- c++ -------------
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {if(root==nullptr) return {};stack<TreeNode*> stk;vector<int> res;while(!stk.empty() || root){ //stack不可以转换成bool类型if (root){res.push_back(root->val);stk.push(root);root=root->left;}else{TreeNode* tem=stk.top();stk.pop();root=tem->right;}}return res;}
};
2、中序遍历
94. 二叉树的中序遍历 - 力扣(LeetCode)
------------- python -------------
class Solution(object):def inorderTraversal(self, root):""":type root: TreeNode:rtype: List[int]"""# res = []# def dfs(root):# if not root:# return# # 按照 左-打印-右的方式遍历 # dfs(root.left)# res.append(root.val)# dfs(root.right)# dfs(root)# return res# 上面是递归res = []stack = []while stack or root:# 不断往左子树方向走,每走一次就将当前节点保存到栈中# 这是模拟递归的调用if root:stack.append(root)root = root.left# 当前节点为空,说明左边走到头了,从栈中弹出节点并保存# 然后转向右边节点,继续上面整个过程else:tmp = stack.pop()res.append(tmp.val)root = tmp.rightreturn res
------------- c++ -------------
// 不可写成while(stack) stack不能转化成bool类型,但是root如果是个指针可以
class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int>res;stack<TreeNode*>stk;while(root!=nullptr || !stk.empty()){if(root!=nullptr){stk.push(root);root=root->left;}else{root=stk.top();stk.pop();res.push_back(root->val);root=root->right;}}return res;}
};
3、后序遍历
145. 二叉树的后序遍历 - 力扣(LeetCode)
------------- python -------------
class Solution:def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:if not root:return []res=[]def dfs(root):if not root:returndfs(root.left)dfs(root.right)res.append(root.val)dfs(root)return res
------------- c++ -------------
class Solution {
public:vector<int> res;void dfs(TreeNode* root){if(root==nullptr) return;dfs(root->left);dfs(root->right);res.push_back(root->val);}vector<int> postorderTraversal(TreeNode* root) {if(root==nullptr) return {};dfs(root);return res;}
};
三、二叉树的层序遍历
1、102 二叉树的层序遍历
102. 二叉树的层序遍历 - 力扣(LeetCode)
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
------------- python -------------
# 利用长度法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:if not root:return []queue = collections.deque([root])result = []while queue:level = []for _ in range(len(queue)):cur = queue.popleft()level.append(cur.val)if cur.left:queue.append(cur.left)if cur.right:queue.append(cur.right)result.append(level)return result
class Solution:def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:if not root:return []levels = []def traverse(node, level):if not node:returnif len(levels) == level:levels.append([])levels[level].append(node.val)traverse(node.left, level + 1)traverse(node.right, level + 1)traverse(root, 0)return levels
------------- c++ -------------
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<vector<int>> result;while (!que.empty()) {int size = que.size();vector<int> vec;// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();vec.push_back(node->val);if (node->left) que.push(node->left);if (node->right) que.push(node->right);}result.push_back(vec);}return result;}
};
# 递归法
class Solution {
public:void order(TreeNode* cur, vector<vector<int>>& result, int depth){if (cur == nullptr) return;if (result.size() == depth) result.push_back(vector<int>());result[depth].push_back(cur->val);order(cur->left, result, depth + 1);order(cur->right, result, depth + 1);}vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;int depth = 0;order(root, result, depth);return result;}
};
2、107 二叉树的层序遍历2
107. 二叉树的层序遍历 II - 力扣(LeetCode)
题目描述:给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
Tips:相对于上一题,把result数组反转。
------------- python -------------
class Solution:"""二叉树层序遍历II迭代解法"""# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:if not root:return []queue = collections.deque([root])result = []while queue:level = []for _ in range(len(queue)):cur = queue.popleft()level.append(cur.val)if cur.left:queue.append(cur.left)if cur.right:queue.append(cur.right)result.append(level)return result[::-1]
------------- c++ -------------
class Solution {
public:vector<vector<int>> levelOrderBottom(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<vector<int>> result;while (!que.empty()) {int size = que.size();vector<int> vec;for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();vec.push_back(node->val);if (node->left) que.push(node->left);if (node->right) que.push(node->right);}result.push_back(vec);}reverse(result.begin(), result.end()); // 在这里反转一下数组即可return result;}
};
3、199 二叉树的右视图
199. 二叉树的右视图 - 力扣(LeetCode)
题目描述:给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
Tips:层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。
------------- python -------------
class Solution:def rightSideView(self, root: TreeNode) -> List[int]:if not root:return []queue = collections.deque([root])right_view = []while queue:level_size = len(queue)for i in range(level_size):node = queue.popleft()if i == level_size - 1:right_view.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return right_view
------------- c++ -------------
class Solution {
public:vector<int> rightSideView(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<int> result;while (!que.empty()) {int size = que.size();for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();if (i == (size - 1)) result.push_back(node->val); // 将每一层的最后元素放入result数组中if (node->left) que.push(node->left);if (node->right) que.push(node->right);}}return result;}
};
4、637 二叉树的层平均值
637. 二叉树的层平均值 - 力扣(LeetCode)
题目描述:给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
------------- python -------------
class Solution:"""二叉树层平均值迭代解法"""# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def averageOfLevels(self, root: TreeNode) -> List[float]:if not root:return []queue = collections.deque([root])averages = []while queue:size = len(queue)level_sum = 0for i in range(size):node = queue.popleft()level_sum += node.valif node.left:queue.append(node.left)if node.right:queue.append(node.right)averages.append(level_sum / size)return averages
------------- c++ -------------
class Solution {
public:vector<double> averageOfLevels(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<double> result;while (!que.empty()) {int size = que.size();double sum = 0; // 统计每一层的和for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();sum += node->val;if (node->left) que.push(node->left);if (node->right) que.push(node->right);}result.push_back(sum / size); // 将每一层均值放进结果集}return result;}
};
5、429 N叉树的层序遍历
429. N 叉树的层序遍历 - 力扣(LeetCode)
题目描述:给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。
------------- python -------------
lass Solution:def levelOrder(self, root: 'Node') -> List[List[int]]:if not root:return []result = []queue = collections.deque([root])while queue:level_size = len(queue)level = []for _ in range(level_size):node = queue.popleft()level.append(node.val)for child in node.children:queue.append(child)result.append(level)return result
------------- c++ -------------
class Solution {
public:vector<vector<int>> levelOrder(Node* root) {queue<Node*> que;if (root != NULL) que.push(root);vector<vector<int>> result;while (!que.empty()) {int size = que.size();vector<int> vec;for (int i = 0; i < size; i++) {Node* node = que.front();que.pop();vec.push_back(node->val);for (int i = 0; i < node->children.size(); i++) { // 将节点孩子加入队列if (node->children[i]) que.push(node->children[i]);}}result.push_back(vec);}return result;}
};
6、515 在每个树行中找最大值
515. 在每个树行中找最大值 - 力扣(LeetCode)
题目描述:在二叉树的每一行中找到最大的值。
------------- python -------------
class Solution:def largestValues(self, root: TreeNode) -> List[int]:if not root:return []result = []queue = collections.deque([root])while queue:level_size = len(queue)max_val = float('-inf')for _ in range(level_size):node = queue.popleft()max_val = max(max_val, node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)result.append(max_val)return result
------------- c++ -------------
class Solution {
public:vector<int> largestValues(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<int> result;while (!que.empty()) {int size = que.size();int maxValue = INT_MIN; // 取每一层的最大值for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();maxValue = node->val > maxValue ? node->val : maxValue;if (node->left) que.push(node->left);if (node->right) que.push(node->right);}result.push_back(maxValue); // 把最大值放进数组}return result;}
};
7、116 填充每个节点的下一个右侧节点指针
116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)
题目描述:给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。
------------- python -------------
class Solution:def connect(self, root: 'Node') -> 'Node':if not root:return rootqueue = collections.deque([root])while queue:level_size = len(queue)prev = Nonefor i in range(level_size):node = queue.popleft()if prev:prev.next = nodeprev = nodeif node.left:queue.append(node.left)if node.right:queue.append(node.right)return root
------------- c++ -------------
class Solution {
public:Node* connect(Node* root) {queue<Node*> que;if (root != NULL) que.push(root);while (!que.empty()) {int size = que.size();// vector<int> vec;Node* nodePre;Node* node;for (int i = 0; i < size; i++) {if (i == 0) {nodePre = que.front(); // 取出一层的头结点que.pop();node = nodePre;} else {node = que.front();que.pop();nodePre->next = node; // 本层前一个节点next指向本节点nodePre = nodePre->next;}if (node->left) que.push(node->left);if (node->right) que.push(node->right);}nodePre->next = NULL; // 本层最后一个节点指向NULL}return root;}
};
8、117 填充2
117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)
题目描述:填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
------------- python -------------
class Solution:def connect(self, root: 'Node') -> 'Node':if not root:return rootqueue = collections.deque([root])while queue:level_size = len(queue)prev = Nonefor i in range(level_size):node = queue.popleft()if prev:prev.next = nodeprev = nodeif node.left:queue.append(node.left)if node.right:queue.append(node.right)return root
------------- c++ -------------
class Solution {
public:Node* connect(Node* root) {queue<Node*> que;if (root != NULL) que.push(root);while (!que.empty()) {int size = que.size();vector<int> vec;Node* nodePre;Node* node;for (int i = 0; i < size; i++) {if (i == 0) {nodePre = que.front(); // 取出一层的头结点que.pop();node = nodePre;} else {node = que.front();que.pop();nodePre->next = node; // 本层前一个节点next指向本节点nodePre = nodePre->next;}if (node->left) que.push(node->left);if (node->right) que.push(node->right);}nodePre->next = NULL; // 本层最后一个节点指向NULL}return root;}
};
9、104 二叉树的最大深度
104. 二叉树的最大深度 - 力扣(LeetCode)
题目描述:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点。
Tips:使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度。
------------- python -------------
class Solution:def maxDepth(self, root: TreeNode) -> int:if not root:return 0depth = 0queue = collections.deque([root])while queue:depth += 1for _ in range(len(queue)):node = queue.popleft()if node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth
------------- c++ -------------
class Solution {
public:int maxDepth(TreeNode* root) {if (root == NULL) return 0;int depth = 0;queue<TreeNode*> que;que.push(root);while(!que.empty()) {int size = que.size();depth++; // 记录深度for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();if (node->left) que.push(node->left);if (node->right) que.push(node->right);}}return depth;}
};
10、111 二叉树的最小深度
111. 二叉树的最小深度 - 力扣(LeetCode)
题目描述:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
------------- python -------------
class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0depth = 0queue = collections.deque([root])while queue:depth += 1 for _ in range(len(queue)):node = queue.popleft()if not node.left and not node.right:return depthif node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth
------------- c++ -------------
class Solution {
public:int minDepth(TreeNode* root) {if (root == NULL) return 0;int depth = 0;queue<TreeNode*> que;que.push(root);while(!que.empty()) {int size = que.size();depth++; // 记录最小深度for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();if (node->left) que.push(node->left);if (node->right) que.push(node->right);if (!node->left && !node->right) { // 当左右孩子都为空的时候,说明是最低点的一层了,退出return depth;}}}return depth;}
};
四、226 翻转二叉树
226. 翻转二叉树 - 力扣(LeetCode)
题目描述:翻转这棵二叉树,并返回其根节点。
递归:1、确定参数和返回;2、确定终止条件;3、单层递归的逻辑
------------- python -------------
class Solution:def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:if not root:return Noneleft=self.invertTree(root.left)right=self.invertTree(root.right)root.left,root.right=right,leftreturn root
------------- c++ -------------
root->left,root->right=right,left;
C++ 不支持这种逗号表达式的赋值方式。
class Solution {
public:TreeNode* invertTree(TreeNode* root) {if(root==nullptr) return nullptr;TreeNode*left=invertTree(root->left);TreeNode*right=invertTree(root->right);root->left=right;root->right=left;return root;}
};
--------------------------------
辅助栈迭代法:代码随想录
class Solution:def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:if not root:return Nonestack=[root]while stack:node=stack.pop()if node.left:stack.append(node.left)if node.right:stack.append(node.right)node.left,node.right=node.right,node.leftreturn root
stack
不支持直接使用花括号进行初始化。正确的方法是先创建一个空栈,然后使用 push
方法添加元素,或者使用 std::vector
来初始化。
class Solution {
public:TreeNode* invertTree(TreeNode* root) {if(root==nullptr) return nullptr;stack<TreeNode*>stk;stk.push(root);while(!stk.empty()){TreeNode*node=stk.top();stk.pop();if(node->left) stk.push(node->left);if(node->right) stk.push(node->right);TreeNode*tem=node->left;node->left=node->right;node->right=tem;}return root;}
};
五、101 对称二叉树
101. 对称二叉树 - 力扣(LeetCode)
题目描述:给定一个二叉树,检查它是否是镜像对称的。
Tips:后序遍历 正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
递归法:
------------- python -------------
注意检查not root (不然无法实现root.left)
我把递归的函数写成成员函数了
class Solution:def dfs(self,left,right):if left is None and right is None:return Trueif not left or not right:return Falseif left.val!=right.val:return Falsereturn self.dfs(left.left,right.right) and self.dfs(left.right,right.left)def isSymmetric(self, root: Optional[TreeNode]) -> bool:if not root:return Truereturn self.dfs(root.left,root.right)
------------- c++ -------------
class Solution {
public:bool dfs(TreeNode*p,TreeNode*q){if(p==nullptr && q==nullptr) return true; //只有一条语句可以省略大括号if(p==nullptr || q==nullptr) return false;if(p->val !=q->val) return false;return dfs(p->left,q->right) && dfs(p->right,q->left);}bool isSymmetric(TreeNode* root) {if(root==nullptr){return true;}return dfs(root->left,root->right);}
};
和94/100的递归比较:相同的树没有使用辅助函数,没必要使用辅助函数可能是由于1、输入参数相同;2、没有其他的需要保留数据的变量如res=[ ]
迭代法:
------------- python -------------
class Solution(object):def isSymmetric(self, root):""":type root: TreeNode:rtype: bool"""if not root or not (root.left or root.right):return True# 用队列保存节点 queue = [root.left,root.right]while queue:# 从队列中取出两个节点,再比较这两个节点left = queue.pop(0)right = queue.pop(0)# 如果两个节点都为空就继续循环,两者有一个为空就返回falseif not (left or right):continueif not (left and right):return Falseif left.val!=right.val:return False# 将左节点的左孩子, 右节点的右孩子放入队列queue.append(left.left)queue.append(right.right)# 将左节点的右孩子,右节点的左孩子放入队列queue.append(left.right)queue.append(right.left)return True
------------- c++ -------------
//用vector实现
class Solution {
public:bool isSymmetric(TreeNode* root) {if(root==nullptr || (root->left==nullptr && root->right==nullptr )) return true;vector<TreeNode*> v;v.push_back(root->left);v.push_back(root->right);while(!v.empty()){TreeNode*left=v[0];v.erase(v.begin());TreeNode*right=v[0];v.erase(v.begin());//如果是v.begin()那么就需要*left->valif(left==nullptr and right==nullptr) continue;if(left==nullptr or right==nullptr) return false;if(left->val != right->val) return false;v.push_back(left->left);v.push_back(right->right);v.push_back(right->left);v.push_back(left->right);}return true;}
};
//用queue实现
class Solution {
public:bool isSymmetric(TreeNode* root) {if (root==nullptr) return true;queue<TreeNode*>q;q.push(root->left);q.push(root->right);while(!q.empty()){TreeNode*l=q.front(); q.pop();TreeNode*r=q.front(); q.pop();if(l==nullptr && r==nullptr) continue;if(l==nullptr || r==nullptr) return false;if(l->val != r->val) return false;q.push(l->left);q.push(r->right);q.push(l->right);q.push(r->left);}return true;}
};
六、222 完全二叉树的节点个数
222. 完全二叉树的节点个数 - 力扣(LeetCode)
很容易的递归但是没有利用完全二叉树的特点:
class Solution(object):def countNodes(self, root):""":type root: TreeNode:rtype: int"""if not root:return 0return self.countNodes(root.left)+self.countNodes(root.right)+1
完全二叉树的定义:它是一棵空树或者它的叶子节点只出在最后两层,若最后一层不满则叶子节点只在最左侧。
------------- python -------------
class Solution(object):def countNodes(self, root):#二叉树的层数def countlevel(root):if not root:return 0return max(countlevel(root.left),countlevel(root.right))+1if not root:return 0left=countlevel(root.left)right=countlevel(root.right)if left==right:return (1<<left)+self.countNodes(root.right)else:return (1<<right)+self.countNodes(root.left)
1<<left 是在计算pow(2,left) <<按位左移
------------- c++ -------------
class Solution {
public:int countlevel(TreeNode* root){if (root==nullptr) return 0;return max(countlevel(root->left),countlevel(root->right))+1;}int countNodes(TreeNode* root) {if (root==nullptr) return 0;int l=countlevel(root->left);int r=countlevel(root->right);if (l==r) return (1<<l)+countNodes(root->right);else return(1<<r)+countNodes(root->left);}
};
七、257 二叉树的所有路径
257. 二叉树的所有路径 - 力扣(LeetCode)
1、递归
深度优先搜索
- 如果当前节点不是叶子节点,则在当前的路径末尾添加该节点,并继续递归遍历该节点的每一个孩子节点。
- 如果当前节点是叶子节点,则在当前路径末尾添加该节点后我们就得到了一条从根节点到叶子节点的路径,将该路径加入到答案即可
------------- python -------------
class Solution:def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:def con_path(root,path):if root:path+=str(root.val)if not root.left and not root.right: #当前节点是叶子节点paths.append(path) #把路径加入到答案中else:path+='->' # 当前节点不是叶子节点,继续递归遍历con_path(root.left,path)con_path(root.right,path)paths=[]con_path(root,'')return paths
------------- c++ -------------
class Solution {
public:void construct_paths(TreeNode* root, string path, vector<string>& paths) {if (root != nullptr) {path += to_string(root->val);if (root->left == nullptr && root->right == nullptr) { // 当前节点是叶子节点paths.push_back(path); // 把路径加入到答案中} else {path += "->"; // 当前节点不是叶子节点,继续递归遍历construct_paths(root->left, path, paths);construct_paths(root->right, path, paths);}}}vector<string> binaryTreePaths(TreeNode* root) {vector<string> paths;construct_paths(root, "", paths);return paths;}
};
时间复杂度和空间复杂度都是O(N方)
2、迭代
广度优先搜索
------------- python -------------
代码中使用 []
的目的是为了初始化 deque
时提供一个初始元素。
class Solution:def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:paths=list()if not root:return pathsnode_queue=collections.deque([root])path_queue = collections.deque([str(root.val)])while node_queue:node = node_queue.popleft()path = path_queue.popleft()if not node.left and not node.right:paths.append(path)else:if node.left:node_queue.append(node.left)path_queue.append(path+'->'+str(node.left.val))if node.right:node_queue.append(node.right)path_queue.append(path + '->' + str(node.right.val))return paths
------------- c++ -------------
class Solution {
public:vector<string> paths;vector<string> binaryTreePaths(TreeNode* root) {if(root==nullptr)return {};deque<TreeNode*>nodes {root};deque<string>path {to_string(root->val)};while(!nodes.empty()){TreeNode* node=nodes.front();nodes.pop_front();string pa=path.front();path.pop_front();if(node->left==nullptr && node->right==nullptr){paths.push_back(pa);}else {if(node->left){nodes.push_back(node->left);path.push_back(pa+"->"+to_string(node->left->val));}if(node->right){nodes.push_back(node->right);path.push_back(pa+"->"+to_string(node->right->val));}}}return paths;}
};
八、404 左叶子之和
404. 左叶子之和 - 力扣(LeetCode)
题目描述:计算给定二叉树的所有左叶子之和。递归法,迭代法。代码随想录
------------- python -------------
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def sumOfLeftLeaves(self, root):if root is None:return 0if root.left is None and root.right is None:return 0leftValue = self.sumOfLeftLeaves(root.left) # 左if root.left and not root.left.left and not root.left.right: # 左子树是左叶子的情况leftValue = root.left.valrightValue = self.sumOfLeftLeaves(root.right) # 右sum_val = leftValue + rightValue # 中return sum_val
递归精简版。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def sumOfLeftLeaves(self, root):if root is None:return 0leftValue = 0if root.left is not None and root.left.left is None and root.left.right is None:leftValue = root.left.valreturn leftValue + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def sumOfLeftLeaves(self, root):if root is None:return 0st = [root]result = 0while st:node = st.pop()if node.left and node.left.left is None and node.left.right is None:result += node.left.valif node.right:st.append(node.right)if node.left:st.append(node.left)return result
------------- c++ -------------
class Solution {
public:int sumOfLeftLeaves(TreeNode* root) {if (root == NULL) return 0;int leftValue = 0;if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) {leftValue = root->left->val;}return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);}
};
class Solution {
public:int sumOfLeftLeaves(TreeNode* root) {stack<TreeNode*> st;if (root == NULL) return 0;st.push(root);int result = 0;while (!st.empty()) {TreeNode* node = st.top();st.pop();if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) {result += node->left->val;}if (node->right) st.push(node->right);if (node->left) st.push(node->left);}return result;}
};
相关文章:
力扣整理版七:二叉树(待更新)
满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。深度为k,有2^k-1个节点的二叉树。 完全二叉树:在完全二叉树中,除了最底层节点可能没填满外&am…...
基于单片机的多功能环保宠物窝设计
本设计基于单片机设计的多功能环保宠物窝,利用温湿度传感器、压力传感模块、气味传感模块、红外测温传感器、通信模块、显示模块、清扫部件等,使其能够实现自动检测并调节温湿度、补充宠物食物、检测宠物体温健康并出现异常时进行报警、自动清扫消毒宠物…...
HBase 基础操作
一、启动HBase 首先,确保Hadoop和HBase服务已经启动。如果尚未启动,可以使用以下命令启动: # 启动Hadoop start-all.sh# 启动HBase start-hbase.sh二、HBase Shell操作 创建表 在HBase Shell中,使用create命令创建表。以下是一…...
小米顾此失彼:汽车毛利大增,手机却跌至低谷
科技新知 原创作者丨依蔓 编辑丨蕨影 三年磨一剑的小米汽车毛利率大增,手机业务毛利率却出现下滑景象。 11月18日,小米集团发布 2024年第三季度财报,公司实现营收925.1亿元,同比增长30.5%,预估902.8亿元;…...
PCL 三维重建 a-shape曲面重建算法
目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 Concave Hull重建 2.1.2 可视化曲面重建结果 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接: PCL点云算法与项目实战案例汇总(长期更新) 一、概述 …...
【Android】线程池的解析
引言 在Android当中根据用途分为主线程与子线程,主线程当中主要处理与界面相关的操作,子线程主要进行耗时操作。除了Thread本身以外,在Android当中还有很多扮演者线程的角色,比如AsyncTask( 底层为线程池,…...
集群聊天服务器(8)用户登录业务
目录 登录状态业务层代码数据模型层代码记录用户的连接信息以及线程安全问题客户端异常退出业务 登录状态 登录且状态变为online 业务层代码 #include "chatservice.hpp" #include "public.hpp" #include <string> #include <muduo/base/Loggi…...
Go语言中的错误嵌套
在Go语言中,错误处理是程序健壮性的关键。Go 1.13版本引入了错误值的嵌套和链式处理,使得错误信息的传递和处理更加灵活和强大。这种机制允许我们在错误中嵌套另一个错误,从而创建一个错误链,这有助于调试和错误跟踪。 错误嵌套的…...
51单片机基础 06 串口通信与串口中断
目录 一、串口通信 二、串口协议 三、原理图 四、串口通信配置参数 1、常用的串行口工作方式1 2、数据发送 3、数据接收 4、波特率计算 5、轮询接收 6、中断接收 一、串口通信 串口通信是一种常见的数据传输方式,广泛用于计算机与外部设备或嵌入式系统之间…...
Elasticsearch:更好的二进制量化(BBQ)对比乘积量化(PQ)
作者:来自 Elastic Benjamin Trent 为什么我们选择花时间研究更好的二进制量化而不是在 Lucene 和 Elasticsearch 中进行生产量化。 我们一直在逐步使 Elasticsearch 和 Lucene 的向量搜索变得更快、更实惠。我们的主要重点不仅是通过 SIMD 提高搜索速度࿰…...
【GNU】gcc -g编译选项 -g0 -g1 -g2 -g3 -gdwarf
1、gcc -g的作用 GCC 的 -g 选项用于在编译时生成调试信息,这些信息会嵌入到生成的目标文件或可执行文件中,主要目的是为了支持调试器(如 gdb)对程序的调试工作。 1.1 生成调试信息 当你在编译代码时使用 -g 选项,GCC…...
MySQL【六】
存储过程 存储过程是一组为了完成特定功能的 SQL 语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。 简单的说存储过程就是具有名字的一段代码。 存储过程的创建 CREATE PROC[ED…...
杰发科技AC7801——ADC定时器触发的简单使用
使用场景 在需要多次采样结果的情况下,比如1s需要10w次的采样结果,可以考虑使用定时器触发采样,定时器设置多少的时间就会多久采样转换一次。 再加上使用dma,采样的结果直接放在dma的数组里面。 实现了自动采样,自动…...
VTK知识学习(8)-坐标系统
1、概述 计算机图形学里常用的坐标系统有4种: 1)、Model坐标系统。定义模型时所采用的坐标系统,通常是局部的笛卡儿坐标系。 2)、World坐标系统。是放置Actor的三维空间坐标系。 Actor(vtkActor类&am…...
IO流部分串讲
一、IO流的概念简析: java将输入与输出比喻为"流",英文:Stream. 就像生活中的"电流","水流"一样,它是以同一个方向顺序移动的过程.只不过这里流动的是字节(2进制数据).所以在IO中有输入流和输出流之分,我们理解他们是连接…...
Excel——宏教程(2)
Excel——宏教程(2) 一)、处理单元格 1、直接赋值与引用 将变量、常量值直接赋给单元格、或将单元格的值直接赋给变量、常量,这是在excel中最简单的单元格赋值及引用方法。 如下例将工作表"Sheet1"A1单元格的值赋给Integer变量I,并将I1的值…...
unity 中 RectTransform 的常用几个属性
RectTransform rectTransform this.GetComponent<RectTransform>(); rectTransform this.transform as RectTransform; Vector3 vector1 rectTransform.position; //自身轴心点相对于锚点的位置(编译器显示的pos) …...
项目-摄像
树莓派摄像头使用方法 Camera教程 https://www.raspi.cc/index.php?cread&id53&page1 nanopc-t4 https://www.raspi.cc/index.php?cread&id53&page1 摄像头型号 Raspberry Pi Camera Rev 1.3 检测故障 dmesg | grep -i mipi piNanoPC-T4:~$ dmesg | …...
摄像机ISP和DSP的区别?
影像处理器是现代数字相机、手机等电子设备中极其重要的一部分,它能够对传感器采集的图像进行多种操作,从而得到更高质量的图像。常见的两种影像处理芯片有ISP(Image Signal Processor)和DSP(Digital Signal Processor…...
Ubuntu24安装配置NDK
1、下载NDK 下载压缩包,下载地址如下,建议下载LTS支持版本。 https://developer.android.google.cn/ndk/downloads?hlcs 2、解压缩 将NDK解压到指定文件夹。如:/opt 或者先解压,再移动到指定目录下。 3、配置环境变量 找到…...
【Next】中间件
概述 Next.js 的 中间件 (Middleware) 是一种在请求完成之前运行的函数,用于对入站请求进行处理和操作。它可以在路由匹配前执行逻辑,用于身份验证、请求重写、重定向、设置响应头等任务。 使用场景 身份验证:在用户访问页面前检查登录状态…...
Vulnhub靶场案例渗透[11]- Momentum2
文章目录 一、靶场搭建1. 靶场描述2. 下载靶机环境3. 靶场搭建 二、渗透靶场1. 确定靶机IP2. 探测靶场开放端口及对应服务3. 扫描网络目录结构4. 代码审计5. 反弹shell6. 提权 一、靶场搭建 1. 靶场描述 - Difficulty : medium - Keywords : curl, bash, code reviewThis wor…...
STM32设计防丢防摔智能行李箱-分享
目录 目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 1.电路图采用Altium Designer进行设计: 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 随着科技的不断发展,嵌入式系统、物联网技术、智能设备…...
Vue Mixin混入机制
在 Vue.js 中,Mixin(混入)是一种可复用代码的机制,用于在多个组件之间共享逻辑。通过混入,可以将通用功能提取到一个独立的文件中,然后在组件中引入并使用,而无需重复代码。 基本概念 Mixin 是…...
数据库类型建表
接着上次的数据库笔记: 初始数据库 (是博主自己写的) 1.数据库类型 1.1数值类型 数据类型大小说明对应JAVA类型BIT[(M)]M指定位数,默认值为1二进制数,M的范围从1—64,存储数值范围从0—2^M-1常用Bool…...
iOS 18 导航栏插入动画会导致背景短暂变白的解决
问题现象 在最新的 iOS 18 系统中,如果我们执行导航栏的插入动画,可能会造成导航栏背景短暂地变为白色: 如上图所示:我们分别向主视图和 Sheet 弹出视图的导航栏插入了消息,并应用了动画效果。可以看到,前者的导航栏背景会在消息插入那一霎那“变白”,而后者则没有任何…...
深度学习之人脸检测
在目标检测领域可以划分为了人脸检测与通用目标检测,往往人脸这方面会有专门的算法(包括人脸检测、人脸识别、人脸其他属性的识别等等),并且和通用目标检测(识别)会有一定的差别,着主要来源于人…...
解决前后端发版本时候,手动清除浏览器缓存
在.html页面中添加标签 后端配置nginx,让index.html不缓存 location /index.html { add_header Cache-Control “no-cache, no-store”; }在vite.config.ts中添加 rollupOpyions: { output: { // 输出编译后的文件名称:【文件名称.时间戳】、【文件名称.版本号.…...
mysql8.4+mysql router读写分离
以下为容器环境内搭建 准备工作: 拉取镜像: 镜像版本mysql8.4container-registry.oracle.com/mysql/community-router8.4 下载mysql_shell mysql-shell-9.0.1-linux-glibc2.17-x86-64bit.tar.gz 下载地址: https://downloads.mysql.com/archives/shell/ 参考 这里对这篇文章…...
鸿蒙NEXT开发-用户通知服务的封装和文件下载通知
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…...
ui设计的网站/企业seo如何优化
下载源码和示例1 原理:启动一个线程来刷时间,缺点是不太精确,可能跟线程的优先级有关系。会有0-10ms的误差。精确到0.1s是没有问题的。packagetimer;publicclassTimer ...{ private long interval; // private boolean enabled; pri…...
中山做app网站公司哪家好/爱站网的关键词是怎么来的
2019独角兽企业重金招聘Python工程师标准>>> 自己自学python,偶然间看到笨方法学python(作者是Zed Shaw)这一本书,在接下来的一段时间内,会完成书中所有的练习,希望自己能坚持下去,能够养成好习惯:读和写、注重细节、发现不同。 祝自己好运! 相应的环境: ubuntu 12.…...
移动论坛网站模板/seo推广哪家好
引言LabVIEW是一种简单易学、形象直观的图形化编程语言,也称为G语言,具有丰富的同传统仪器外观类似的控件库(如旋钮、仪表盘、温度计、波形图表等),可以构建漂亮专业的用户界面,同时,内部提供了庞大的函数库(如数据采集…...
这种资源网站怎么做才赚钱/河南网站推广多少钱
文章目录同分支pick操作流程:跨分支pick同分支pick git cherry-pick commit_id 可以将制定commit id的数据pick到当前 操作流程: 首先: A)git cherry-pick 制定commit_id 【注意】: 如果没有冲突的话,就p…...
智能建站系统的建站步骤/免费的精准引流软件
微控电子万能试验机主要用于金属材料非金属材料复合材料高分子材料等在常温或者高低温环境下的拉伸、压缩、弯曲、剪切、剥离、撕裂、保载等项的静态力学性能测试分析研究,可自动求取ReH、ReL、Rp0.2、Fm、Rt0.5 、Rt0.6、Rt0.65、Rt0.7、Rm、E等试验参数࿰…...
太原免费网站建设/seo关键词推广话术
好久没写东西了,去年用了angular2的RC版本和ionic2写了一个项目,因为开发周期和有些版本不稳定,所以一直没有升级,ng2新版本引用Aot打包,听说优化还不错,现在尝试升级ionic2、angular2到最新版本࿰…...