代码随想录算法训练营第十一天 | 二叉树系列2

二叉树系列2

  • 101 对称二叉树
    • 二叉树很重要的一点:确定遍历顺序
    • 关于递归
    • 代码随想录的代码
    • 我的代码(理解后编写)
  • 100 相同的树
    • 我的代码
  • 572 另一个树的子树
    • 我的代码
    • 录友的代码,只用递归!!!
  • 104 二叉树的最大深度
    • 重点
    • 代码随想录的代码
    • 我的代码(理解后自己写)
  • 559 N 叉树的最大深度
    • 代码随想录的代码
    • 我的代码
  • 111 二叉树的最小深度
    • 代码随想录的代码
    • 二刷要着重自己独立编写
  • 222 完全二叉树的节点个数
    • 代码随想录的代码
    • 二刷要着重自己独立编写
  • 110 平衡二叉树
    • 我的代码
    • 代码随想录的代码
  • 257 二叉树的所有路径
    • 重点
    • 代码随想录的代码
    • 此题很难,二刷时要注意
  • 二刷要着重自己独立编写
  • 二叉树系列2总结

101 对称二叉树

直接阅读的代码随想录的解答。

该用哪种遍历顺序?这很重要

本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。
正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
但都可以理解算是后序遍历,尽管已经不是严格上在一个树上进行遍历的后序遍历了。其实后序也可以理解为是一种回溯,当然这是题外话,讲回溯的时候会重点讲的。

三种方法,递归,迭代队列,迭代栈。

难点在于递归终止条件的判断。
在这里插入图片描述
迭代法要注意:

在迭代法中使用了队列,需要注意的是这不是层序遍历,而且仅仅通过一个容器来成对的存放我们要比较的元素,知道这一本质之后就发现,用队列,用栈,甚至用数组,都是可以的。

二叉树很重要的一点:确定遍历顺序

需要收集孩子的信息,向上一层返回的题,要用后序遍历,左右中。

关于递归

这里写递归时可以发现,只要一个子递归函数返回了False,那么最终结果一定为False,没必要执行剩下的递归,但是递归函数中的return是无法做到强制跳出了,搜了一下,使用抛出异常的方式,跳出。

如果是Python语言,搜索了一下,网上给出的方法是:使用一个布尔型的全局变量。

代码随想录的代码

递归:

class Solution:def isSymmetric(self, root: TreeNode) -> bool:if not root:return Truereturn self.compare(root.left, root.right)def compare(self, left, right):#首先排除空节点的情况if left == None and right != None: return Falseelif left != None and right == None: return Falseelif left == None and right == None: return True#排除了空节点,再排除数值不相同的情况elif left.val != right.val: return False#此时就是:左右节点都不为空,且数值相同的情况#此时才做递归,做下一层的判断outside = self.compare(left.left, right.right) #左子树:左、 右子树:右inside = self.compare(left.right, right.left) #左子树:右、 右子树:左isSame = outside and inside #左子树:中、 右子树:中 (逻辑处理)return isSame

迭代法:使用队列

import collections
class Solution:def isSymmetric(self, root: TreeNode) -> bool:if not root:return Truequeue = collections.deque()queue.append(root.left) #将左子树头结点加入队列queue.append(root.right) #将右子树头结点加入队列while queue: #接下来就要判断这这两个树是否相互翻转leftNode = queue.popleft()rightNode = queue.popleft()if not leftNode and not rightNode: #左节点为空、右节点为空,此时说明是对称的continue#左右一个节点不为空,或者都不为空但数值不相同,返回falseif not leftNode or not rightNode or leftNode.val != rightNode.val:return Falsequeue.append(leftNode.left) #加入左节点左孩子queue.append(rightNode.right) #加入右节点右孩子queue.append(leftNode.right) #加入左节点右孩子queue.append(rightNode.left) #加入右节点左孩子return True

迭代法:使用栈

class Solution:def isSymmetric(self, root: TreeNode) -> bool:if not root:return Truest = [] #这里改成了栈st.append(root.left)st.append(root.right)while st:rightNode = st.pop()leftNode = st.pop()if not leftNode and not rightNode:continueif not leftNode or not rightNode or leftNode.val != rightNode.val:return Falsest.append(leftNode.left)st.append(rightNode.right)st.append(leftNode.right)st.append(rightNode.left)return True

层次遍历:

class Solution:def isSymmetric(self, root: TreeNode) -> bool:if not root:return Truequeue = collections.deque([root.left, root.right])while queue:level_size = len(queue)if level_size % 2 != 0:return Falselevel_vals = []for i in range(level_size):node = queue.popleft()if node:level_vals.append(node.val)queue.append(node.left)queue.append(node.right)else:level_vals.append(None)if level_vals != level_vals[::-1]:return Falsereturn True

我的代码(理解后编写)

递归:明确三部曲即可。

class Solution:def isSymmetric(self, root: Optional[TreeNode]) -> bool:if root == None :return Truereturn self.isequal(root.left,root.right)def isequal(self,left,right):if left == None and right == None :return Trueelif left != None and right == None :return Falseelif left == None and right != None :return Falseelif left.val != right.val :return Falseelse :isleft = self.isequal(left.left,right.right)isright = self.isequal(left.right,right.left)return isleft and isright

递归(强制退出,无法运行的错误代码):似乎不需要了解这种情况了

class Solution:def isSymmetric(self, root: Optional[TreeNode]) -> bool:if root == None :return Trueglobal judgejudge=Trueself.isequal(root.left,root.right,judge)return judgedef isequal(self,left,right,judge):if judge :if left == None and right == None :return Trueelif left != None and right == None :judge = Falsereturn Falseelif left == None and right != None :judge = Falsereturn Falseelif left.val != right.val :judge = Falsereturn Falseelse :isleft = self.isequal(left.left,right.right,judge)isright = self.isequal(left.right,right.left,judge)return isleft and isrightelse :return False

递归(强制退出,用self定义了类内的全局变量)

class Solution:def __init__(self):self.judge = Truedef isSymmetric(self, root: Optional[TreeNode]) -> bool:if root == None :return Trueself.isequal(root.left,root.right,self.judge)return self.judgedef isequal(self,left,right,judge):if self.judge :if left == None and right == None :return Trueelif left != None and right == None :self.judge = Falsereturn Falseelif left == None and right != None :self.judge = Falsereturn Falseelif left.val != right.val :self.judge = Falsereturn Falseelse :isleft = self.isequal(left.left,right.right,judge)isright = self.isequal(left.right,right.left,judge)self.judge = isleft and isrightreturn self.judgeelse :return False

迭代法:使用队列
编写要点:在此队列中,None是要加入队列的,如果left和right均为None,就continue。

from collections import deque
class Solution:def isSymmetric(self, root: Optional[TreeNode]) -> bool:if root == None :return Truedq = deque()dq.append(root.left)dq.append(root.right)while dq :left = dq.popleft()right = dq.popleft()if left == None and right == None :continueelif left != None and right == None : return Falseelif left == None and right != None :return Falseelif left.val != right.val :return Falseelse :dq.append(left.left)dq.append(right.right)dq.append(left.right)dq.append(right.left)return True

迭代法:使用栈

class Solution:def isSymmetric(self, root: Optional[TreeNode]) -> bool:if root == None :return Truest = []st.append(root.left)st.append(root.right)while st :left = st.pop()right = st.pop()if left == None and right == None :continueelif left != None and right == None : return Falseelif left == None and right != None :return Falseelif left.val != right.val :return Falseelse :st.append(left.left)st.append(right.right)st.append(left.right)st.append(right.left)return True

层次遍历,用deque

from collections import deque
class Solution:def isSymmetric(self, root: Optional[TreeNode]) -> bool:if root == None :return Truestack = deque()stack.append(root.left)stack.append(root.right)while stack :size = len(stack)if size % 2 != 0:return Falseres = []for i in range(size):node = stack.popleft()if node :res.append(node.val)stack.append(node.left)stack.append(node.right)else :res.append(None)if res != res[::-1] :return Falsereturn True

100 相同的树

我的代码

一刷只写了递归法,其他方法二刷再写

class Solution:def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:if p == None and q == None :return Trueelif p != None and q == None:return Falseelif p == None and q != None:return Falseelif p.val != q.val :return Falseelse :left = self.isSameTree(p.left,q.left)right = self.isSameTree(p.right,q.right)return left and right

572 另一个树的子树

我的代码

一刷虽然通过了,但方法是层次遍历+递归相等树判断,去遍历每一个节点,代码显得冗余

from collections import deque
class Solution:def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:if root == None and subRoot == None :return Trueelif root != None and subRoot == None:return Falseelif root == None and subRoot != None:return Falseelse :dq = deque()dq.append(root)while dq:size = len(dq)for i in range(size):node = dq.popleft()if node :judge = self.isSameTree(node,subRoot)if judge :return Truedq.append(node.left)dq.append(node.right)return Falsedef isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:if p == None and q == None :return Trueelif p != None and q == None:return Falseelif p == None and q != None:return Falseelif p.val != q.val :return Falseelse :left = self.isSameTree(p.left,q.left)right = self.isSameTree(p.right,q.right)return left and right

录友的代码,只用递归!!!

一个树是另一个树的子树,则:要么这两个树相等;要么这个树是左树的子树;要么这个树hi右树的子树

又因为提议可知,子树不为None,所以递归的判断环节可以简化。

但是这样只用递归,在时间消耗上比我的层次遍历稍高。

class Solution:def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:  if root == None :return Falseelse :jg1 = self.isSameTree(root,subRoot)jg2 = self.isSubtree(root.left,subRoot)jg3 = self.isSubtree(root.right,subRoot)return jg1 or jg2 or jg3def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:if p == None and q == None :return Trueelif p != None and q == None:return Falseelif p == None and q != None:return Falseelif p.val != q.val :return Falseelse :left = self.isSameTree(p.left,q.left)right = self.isSameTree(p.right,q.right)return left and right

104 二叉树的最大深度

用层次遍历的方法,是层次遍历的模板题,这里只学习使用递归的方法。

重点

搞清楚,深度和高度的区别。

高度:从上到下,3 2 1 。深度:从上到下:1 2 3 。

求高度,从下向上计数,为后序遍历,左右中,有一个中,就加一。求深度,从上向下计数,为前序遍历,中左右,有一个中,就加一。

根节点的高度,就是这颗二叉树的最大深度。

代码随想录的代码

后序遍历:(求高度)

class solution:def maxdepth(self, root: treenode) -> int:return self.getdepth(root)def getdepth(self, node):if not node:return 0leftheight = self.getdepth(node.left) #左rightheight = self.getdepth(node.right) #右height = 1 + max(leftheight, rightheight) #中return height

前序遍历:(求深度)
不推荐,不学习。二刷时再说。放一个Java的代码,着重看回溯的过程。

class Solution {
public:int result;void getDepth(TreeNode* node, int depth) {result = depth > result ? depth : result; // 中if (node->left == NULL && node->right == NULL) return ;if (node->left) { // 左depth++;    // 深度+1getDepth(node->left, depth);depth--;    // 回溯,深度-1}if (node->right) { // 右depth++;    // 深度+1getDepth(node->right, depth);depth--;    // 回溯,深度-1}return ;}int maxDepth(TreeNode* root) {result = 0;if (root == 0) return result;getDepth(root, 1);return result;}
};

我的代码(理解后自己写)

后序遍历:(求高度)

class Solution:def maxDepth(self, root: Optional[TreeNode]) -> int:if root == None :return 0left = self. maxDepth(root.left)right = self. maxDepth(root.right)return 1+max(left,right)

前序遍历:(求深度)
不推荐,不学习。二刷时再说。

559 N 叉树的最大深度

后序遍历,根节点的高度就是最大深度。

代码随想录的代码

class Solution:def maxDepth(self, root: 'Node') -> int:if not root:return 0max_depth = 1for child in root.children:max_depth = max(max_depth, self.maxDepth(child) + 1)return max_depth

我的代码

class Solution:def maxDepth(self, root: 'Node') -> int:if root == None :return 0res = []n = len(root.children)if n==0 :return 1else :for i in root.children :res.append(self.maxDepth(i))depth = 1 + max(res)return depth

111 二叉树的最小深度

用层次遍历的方法,是层次遍历的模板题,这里只学习使用递归的方法。

同样使用后续遍历。

此题一定要注意最小深度的定义,是叶子节点到根节点的最短距离,而叶子节点的定义为:左右孩子均为None 。

很容易错的一道题,没弄明白之前,递归逻辑也不好写。

注意避开陷阱!当只有一个孩子为None时,返回的是 1+不为空子树的最小高度。

代码随想录的代码

后序+递归:

class Solution:def getDepth(self, node):if node is None:return 0leftDepth = self.getDepth(node.left)  # 左rightDepth = self.getDepth(node.right)  # 右# 当一个左子树为空,右不为空,这时并不是最低点if node.left is None and node.right is not None:return 1 + rightDepth# 当一个右子树为空,左不为空,这时并不是最低点if node.left is not None and node.right is None:return 1 + leftDepthresult = 1 + min(leftDepth, rightDepth)return resultdef minDepth(self, root):return self.getDepth(root)

前序+递归:这里用 init 定义一个self的全局变量的思路,很值得学习。隐藏了回溯的思想,每次递归时,并未改变depth。

class Solution:def __init__(self):self.result = float('inf')def getDepth(self, node, depth):if node is None:returnif node.left is None and node.right is None:self.result = min(self.result, depth)if node.left:self.getDepth(node.left, depth + 1)if node.right:self.getDepth(node.right, depth + 1)def minDepth(self, root):if root is None:return 0self.getDepth(root, 1)return self.result

二刷要着重自己独立编写

这里写的就不如代码随想录给出的标准答案,调用递归次数过多,就应该在第一个 if 判断后,就去统计左右深度。

class Solution:def minDepth(self, root: Optional[TreeNode]) -> int:if root == None :return 0if root.left == None and root.right == None :return 1elif root.left == None :return 1 + self.minDepth(root.right)elif root.right == None :return 1 + self.minDepth(root.left)else :return 1 + min(self.minDepth(root.left),self.minDepth(root.right))

222 完全二叉树的节点个数

迭代法依然是层序遍历的蓝本。递归法也好理解,递归的目标是左右子树的节点个数。值得学习的是,利用完全二叉树的性质,来写出时间复杂度更低的代码。

递归,依然是后序遍历,本质上和其高度类似,只不过递归逻辑由求高度,变为了求数量。

代码随想录的代码

递归:

class Solution:def countNodes(self, root: TreeNode) -> int:return self.getNodesNum(root)def getNodesNum(self, cur):if not cur:return 0leftNum = self.getNodesNum(cur.left) #左rightNum = self.getNodesNum(cur.right) #右treeNum = leftNum + rightNum + 1 #中return treeNum

利用完全二叉树:

class Solution:def countNodes(self, root: TreeNode) -> int:if not root:return 0left = root.leftright = root.rightleftDepth = 0 #这里初始为0是有目的的,为了下面求指数方便rightDepth = 0while left: #求左子树深度left = left.leftleftDepth += 1while right: #求右子树深度right = right.rightrightDepth += 1if leftDepth == rightDepth:return (2 << leftDepth) - 1 #注意(2<<1) 相当于2^2,所以leftDepth初始为0return self.countNodes(root.left) + self.countNodes(root.right) + 1

二刷要着重自己独立编写

利用完全二叉树:

class Solution:def countNodes(self, root: Optional[TreeNode]) -> int:if root == None :return 0leftnode =  root.leftrightnode = root.rightln = 1rn = 1while leftnode :leftnode = leftnode.leftln += 1while rightnode :rightnode = rightnode.rightrn += 1if ln == rn :return 2**ln - 1else :return 1+self.countNodes(root.left)+self.countNodes(root.right)

110 平衡二叉树

使用递归的思想编写,不用迭代方法,首先此题不能用层序遍历,迭代法无法很好地模拟回溯过程,中间存在很多重复计算。

具体分析参考代码随想录的文章即可。
平衡二叉树

我的代码

发现,我现在写递归,很喜欢加一个全局变量来做判断了,也不知道是好是坏。

所以还是学习一下的代码随想录的解答方式。

class Solution:def __init__(self):self.judge = Truedef isBalanced(self, root: Optional[TreeNode]) -> bool:self.digui(root)return self.judgedef digui(self,root):if root == None :return 0if self.judge :left = self.digui(root.left)right = self.digui(root.right)if abs(left-right) > 1 :self.judge = Falsereturn 1 + max(left,right)else :return 0

代码随想录的代码

其实对递归了解较深之后,这样一层一层返回-1,和搞一个self变量是一样的效果!!!

所以还是学习下面这种写法吧。

class Solution:def isBalanced(self, root: TreeNode) -> bool:if self.get_height(root) != -1:return Trueelse:return Falsedef get_height(self, root: TreeNode) -> int:# Base Caseif not root:return 0# 左if (left_height := self.get_height(root.left)) == -1:return -1# 右if (right_height := self.get_height(root.right)) == -1:return -1# 中if abs(left_height - right_height) > 1:return -1else:return 1 + max(left_height, right_height)

257 二叉树的所有路径

第一道,递归+回溯的题目!!!

回溯一直是没有掌握的点!!!

直接学习代码随想录的解答。文章链接如下。
二叉树的所有路径

重点

同样需要先确定遍历顺序,肯定为前序遍历,因为输出路径为父节点指向子节点,中序和后序,无法得到父节点到子节点的指向。

所谓隐藏回溯,就是对Path做拷贝操作,这样在后序递归时,对Path的修改,不会影响到上一层的其他带Path的语句,所以不需要回溯操作。

对于Python来说,对同一个变量进行操作,所有的地方都会发生改变,类似于C语言中对地址的操作,想要不改变原变量,就要用copy()操作。

代码随想录的代码

递归法+回溯

class Solution:def traversal(self, cur, path, result):path.append(cur.val)  # 中if not cur.left and not cur.right:  # 到达叶子节点sPath = '->'.join(map(str, path))result.append(sPath)returnif cur.left:  # 左self.traversal(cur.left, path, result)path.pop()  # 回溯if cur.right:  # 右self.traversal(cur.right, path, result)path.pop()  # 回溯def binaryTreePaths(self, root):result = []path = []if not root:return resultself.traversal(root, path, result)return result

递归法+隐形回溯(版本一)

from typing import List, Optionalclass Solution:def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:if not root:return []result = []self.traversal(root, [], result)return resultdef traversal(self, cur: TreeNode, path: List[int], result: List[str]) -> None:if not cur:returnpath.append(cur.val)if not cur.left and not cur.right:result.append('->'.join(map(str, path)))if cur.left:self.traversal(cur.left, path[:], result)if cur.right:self.traversal(cur.right, path[:], result)

递归法+隐形回溯(版本二)

class Solution:def binaryTreePaths(self, root: TreeNode) -> List[str]:path = ''result = []if not root: return resultself.traversal(root, path, result)return resultdef traversal(self, cur: TreeNode, path: str, result: List[str]) -> None:path += str(cur.val)# 若当前节点为leave,直接输出if not cur.left and not cur.right:result.append(path)if cur.left:# + '->' 是隐藏回溯self.traversal(cur.left, path + '->', result)if cur.right:self.traversal(cur.right, path + '->', result)

迭代法(有些难理解的)

class Solution:def binaryTreePaths(self, root: TreeNode) -> List[str]:# 题目中节点数至少为1stack, path_st, result = [root], [str(root.val)], []while stack:cur = stack.pop()path = path_st.pop()# 如果当前节点为叶子节点,添加路径到结果中if not (cur.left or cur.right):result.append(path)if cur.right:stack.append(cur.right)path_st.append(path + '->' + str(cur.right.val))if cur.left:stack.append(cur.left)path_st.append(path + '->' + str(cur.left.val))return result

此题很难,二刷时要注意

二刷要着重自己独立编写

递归法+回溯

class Solution:def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:if root == None :return Noneres = []path = []self.digui(root,path,res)return resdef digui(self,cur,path,res):path.append(cur.val)if cur.left == None and cur.right == None :sPath = '->'.join(map(str, path))res.append(sPath)return if cur.left :self.digui(cur.left,path,res)path.pop()if cur.right :self.digui(cur.right,path,res)path.pop()

二叉树系列2总结

直接放代码随想录总结文章的链接。
二叉树系列2总结

回溯法其实就是递归,但是很少人用迭代的方式去实现回溯算法!

讲了这么多二叉树题目的迭代法,有的同学会疑惑,迭代法中究竟什么时候用队列,什么时候用栈?

如果是模拟前中后序遍历就用栈,如果是适合层序遍历就用队列,当然还是其他情况,那么就是 先用队列试试行不行,不行就用栈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/12988.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

17.OpenCV中的GFTTDetector类

文章目录 GFTTDetector功能OpenCV中GFTTDetector类reference 欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 这是使用imgproc.hpp中的goodFeaturesToTrack函数封装的类&#xff0c;其使用和goodFeaturesToTrack函数基本相似。 GFTTDetec…

【算法与数据结构】20、LeetCode有效的括号

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;括号匹配是使用栈解决的经典问题。做这道题首先要分析什么时候括号不匹配。1、右括号多余 ( { [ ] } )…

PCL 法向量估计源码学习

一、思路&#xff1a; 二、源码 #ifndef PCL_FEATURES_IMPL_NORMAL_3D_H_ #define PCL_FEATURES_IMPL_NORMAL_3D_H_#include <pcl/features/normal_3d.h>/// template <typename PointInT, typename PointOutT> void pcl::NormalEstimation<PointInT, PointOutT…

【stability.ai】SDXL:改进高分辨率图像合成的潜在扩散模型

github&#xff1a;https://github.com/Stability-AI/stablediffusion 试用&#xff1a; https://clipdrop.co/stable-diffusion https://dreamstudio.ai/ 介绍 近年来&#xff0c;深度生成建模在自然语言、音频和视觉媒体等各个数据领域取得了巨大的突破。本文将重点关注视…

nohup命令解决SpringBoot/java -jar命令启动项目运行一段时间自动停止问题

问题描述&#xff1a; 在centos7上部署多个springcloud项目。出现了服务莫名其妙会挂掉一两个的问题&#xff0c;重新启动挂掉的服务之后又会出现其他服务挂掉的情况&#xff0c;查看启动日志也并没有发现有异常抛出。令人费解的是所有的服务都是通过nohup java -jar xxx.jar …

TCP / IP 参考模型

TCP / IP 参考模型 5层参考模型5层参考模型5层模型的数据封装 5层参考模型 5层参考模型 综合 OSI 和 TCP/IP 的优点应用层: 支持各种网络应用 FTP, SMTP, HTTP 传输层: 进程-进程的数据传输 TCP, UDP 网络层: 源主机到目的主机的数据分组路由与转发 IP协议、路由协议等 链路层…

JS中的扁平化数据转换为树形结构数组

递归方法和循环方法&#xff0c;我都写了两种代码&#xff0c;仅供参考。 三种递归方法&#xff0c;两种循环方法&#xff0c;本质上都一样&#xff0c;就是写法不一样&#xff0c;加油&#xff01;&#xff01;&#xff01; // 数据 const arr [{ id: 1, name: 广东, pid:…

还在手动下载github项目?想要自动化下载github项目?基于python开发项目自动下载模块帮你实现自动下载存储

GitHub是一个基于Web的代码托管平台和开发者社区。它允许开发者存储、管理和分享他们的代码&#xff0c;并进行版本控制。开发者可以在GitHub上创建仓库来存储项目代码&#xff0c;并使用Git来跟踪和管理代码的变更历史。GitHub提供了一系列协作工具&#xff0c;如问题追踪、Pu…

Vue实现在线文档预览

目录 背景在线预览Office文档文件在线预览pdf文档预览方案一方案二 Word文档预览Excel文档预览PPT文档预览 纯文本、各种代码文件预览图片文件预览视频文件预览Aliplayer阿里云播放器Xgplayer西瓜播放器Bilibiliplayer仿哔哩哔哩弹幕播放器 音频文件预览在线文档预览项目&#…

POE级联蓝牙定位系统方案_蓝牙信标,蓝牙网关,级联蓝牙网关

近年来,随着新能源行业的快速发展,在化工厂,核电厂以及电力电厂等企业,对人员定位,人员导航,资产定位,生命体征监测的需求越来越大。传统的蓝牙室内定位方案中蓝牙信标为锂亚电池供电,需定期更换电池且有安全隐患,为更好的服务有蓝牙定位导航,被动人员定位,生命体征…

MySQL之概述、安装和使用(一)

一、概述 关系数据库概述&#xff1a; https://blog.csdn.net/qq_21370419/article/details/128568920 二、数据库的安装 参考我的两篇博客&#xff1a; win10 安装mysql 5.6.36版本_windows 安装mysql5.6_人……杰的博客-CSDN博客 wind 10 安装 mysql 8.0_人……杰的博客…

50从零开始学Java之万类之王Object是怎么回事?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在前面的文章中&#xff0c;壹哥跟大家说过&#xff0c;Java是面向对象的编程语言&#xff0c;而在面…